home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
COMM
/
MSKRMSRC.ARJ
/
MSYIBM.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-10-24
|
144KB
|
4,607 lines
NAME msyibm
; File MSYIBM.ASM
include mssdef.h
; Copyright (C) 1982,1991, Trustees of Columbia University in the
; City of New York. Permission is granted to any individual or
; institution to use, copy, or redistribute this software as long as
; it is not sold for profit and this copyright notice is retained.
; edit history:
; 6 Sept 1991 version 3.11
; Last edit 6 Sept 1991
; 23 Dec 1990 Add Bert Tyler's (NIH) IBM XGA 132 column code.
; 9 May 1989 Add Bert Tyler's (NIH) new screen rollback routines.
; 21 Jan 1989 be more tolerate of propriatary video modes above 18 when
; determining screen segment, Tnx to Terry Kennedy. Add check for IBM
; 85xx monitors on Video 7 boards, no 132 columns if it is the monitor.
; Retain 43 rows on Video 7 boards.
; 30 Nov 1988 Add SET TERM CLEAR screen clearing support.
; 28 Nov 1988 Accomodate Tseng Labs UltraPAK mono/Herc board w/132 cols.
; 132 column mode is 18h. Requires Tseng's BIGSCR.COM (use BIGSCR /R:25
; to enable 132x25 feature). Thanks to Tseng Labs for technical support.
; 21 Nov 1988 Version 2.32
; 14 Nov 1988 Write a space during lclini to obtain default screen colors.
; 12 Nov 1988 Add procs vtrmac and vtsmac to allow exit from Connect mode and
; invokation of macros TERMINALR and TERMINALS by reception of escape seqs
; in file mszibm.asm or by keyboard verbs.
; 7 Oct 1988 Reverse left/right arrow key codes when writing right to left.
; 24 Sept 1988 Make output to printer be buffered and flow controlled.
; 1 July 1988 Version 2.31
; 19 June 1988 Add Everex EVGA support, from Terry Kennedy.
; 10 June 1988 Add oldsp and procedure endcon to exit Connect mode if output
; fails, mostly for networking (but we don't know that here).
; 23 May 1988 Add Everex EV-659 ega board test from Alex Zliu. Fixed incorrect
; screen width assumption at startup.
; 29 March 1988 Include flag ttyact to group string bytes into one net packet,
; thanks to Paul Fox of AT&T.
; 23 March 1988 Add "fairness" word to let serial port deliver max chars
; between kbd reads, for connect mode only. [jrd]
; 10 Feb 1988 Revise getcirc and vtscrX routines to do proper scrolling with
; MS Window 1.0x/2.0x [jrd].
; 9 Feb 1988 Mode line again. Make flags.modflg 0 for off, 1 for on and owned
; by Kermit, and 2 for on and owned by remote host (toggling suppressed).
; 25 Jan 1988 Add global byte SCROLL, set in msz, to control emulator screen
; scrolling for higher speeds. [jrd]
; 5 Jan 1988 Restore cursor codes broken by Tek code additions. [jrd]
; 1 Jan 1988 version 2.30
public term, lclyini ; entry points
public prtbout, prtnout, csrtype, scrseg
public atsclr, vtscru, vtscrd, trnmod, vclick, vtbell
public chgdsp, vtroll, crt_lins, crt_cols, tv_mode, vtclear
; action verb procedures for keyboard translator
public uparrw, dnarrw, rtarr, lfarr, pf1, pf2, pf3, pf4
public kp0, kp1, kp2, kp3, kp4, kp5, kp6, kp7, kp8, kp9
public kpminus, kpcoma, kpenter, kpdot, chrout, cstatus, cquit
public cquery, dmpscn, vtans52, vtinit, dnwpg, upwpg, endwnd, homwnd
public upone, dnone, trnprs, dumpscr, modlin, snull
public klogon, klogof, cdos, chang, khold, vtrmac, vtsmac, product
public decf6,decf7,decf8,decf9,decf10,decf11,decf12,decf13,decf14
public dechelp,decdo,decf17,decf18,decf19,decf20, udkclear
public decfind, decinsert, decremove, decselect, decprev
public decnext, setudk, extmacro, vtmacname, vtmaclen
public vtemu, crt_mode, scbattr, refresh, low_rgt ; data
public setchtab
public savescr, restscr ; code
public setpos, getpos, getatch, setatch, putchar, yflags
public getbold, setbold, clrbold, getblink, setblink, clrblink
public getunder, setunder, clrunder, revideo, revscn, setcolor
public setrev, clrrev, insdecom
public vts, vtstat, termtb ; terminal emulation
; some definitions
; hardware
crt_status equ 3dah ; CGA crt status port
disp_enb equ 8 ; CGA display enable bit
crtmset equ 3D8H ; CGA CRT mode set port
screen equ 10h ; Bios screen interrupt
modfrm struc ; format of mode (status) line
db 'Esc-chr: ' ; do not write in last column
m_echr db 2 dup (' ')
db ' help: '
m_hlp db 2 dup (' ')
db '? port:'
m_prt db 1 dup (' ')
db ' speed:'
m_baud db 6 dup (' ')
db 'parity:'
m_par db 4 dup (' ')
db ' echo:'
m_echo db 3 dup (' ')
m_term db 13 dup (' ') ; 13 bytes for term type
m_prn db 3 dup (' ') ; show PRN when printer is on
db '$' ; terminator
modfrm ends
; structure for status information table sttab.
stent struc
sttyp dw ? ; type (actually routine to call)
msg dw ? ; message to print
val2 dw ? ; needed value: another message, or tbl addr
tstcel dw ? ; address of cell to test, in data segment
basval dw 0 ; base value, if non-zero
stent ends
data segment
extrn flags:byte, mar_top:byte, mar_bot:byte, portval:word
extrn filtst:byte, dmpname:byte, kbdflg:byte, rxtable:byte
extrn anspflg:byte, tekflg:byte, scroll:byte, ttyact:byte
extrn holdscr:byte, taklev:byte, takadr:word, mcctab:byte
extrn video_state:byte, trans:byte, npages:word, comand:byte
extrn denyflg:word, tekgraf:byte, rdbuf:byte, dupflg:byte
extrn chcontrol:byte, kbcodes:byte, repflg:byte, tekcursor:byte
extrn decbuf:byte, param:word, nparam:word, prnhand:word
extrn upss:byte, comptab:byte
; stuff for screen routines
yflags db 0 ; status flags
prtscr equ 1 ; print screen pressed
inited equ 08h ; been here before
vtinited db 0 ; flag for emulator having been inited
vtclear db 0 ; nonzero to redo emulator screen
cursor dw 0
parmsk db 0 ; 8/7 bit parity mask, for reception
argadr dw 0 ; address of arg blk
skip dw 0
vid7id db 'VEGA BIOS Code, ' ; Video 7 Vega version string subset
vid7len equ $-vid7id ; length of string
vid7id2 db 'Video Seven BIOS Code, ' ; Video 7 VGA board
vid7len2 equ $-vid7id2
atiwid db 'ATI EGA Wonder Bios,' ; ATI EGA wonder version string subset
atilen equ $-atiwid ; length of string, inc terminator
atiwid2 db '761295520' ; ATI signature #2
atilen2 equ $-atiwid2
tsngid db 'Tseng' ; Tseng Labs EVA (& Orchid Designer)
tsnglen equ $-tsngid
stbvid db 'TVGA' ; STB VGA/EM (also Tseng TVGA)
stbvlen equ $-stbvid
stavid db '4000' ; STB VGA/EM Plus (Tesng 4000)
stavlen equ $-stavid
evrxid db 'Everex' ; Everex Micro Enhancer Deluxe EGA
evrxlen equ $-evrxid
evgid db 'VGA EV673' ; Everex EVGA EV-673
evglen equ $-evgid
evvid db 'EV-678' ; Everex Viewpoint EV-678
evvlen equ $-evvid
attvdc6 db '003116' ; AT&T video board, at c000:35h
attvdlen equ $-attvdc6
attvdc7 db 'C02000' ; AT&T video board, at e000:10h
pmega1 db '28190-A1001' ; Paradise AutoSwitch EGA Mono String1
pmegal1 equ $-pmega1
p30id db 'VGA' ; VGA Plus, Plus 16, Professional
p30ln equ $-p30id ; and VGA1024 by Paradise
cols80 db 'COLS80.BAT',0 ; to 80 column mode batch file
cols132 db 'COLS132.BAT',0 ; to 132 column mode batch file
xga_reg_base dw -1 ; PS/2 MCA I/O register base
ega_mode db 0 ; non-zero if IBM EGA is in use
tvhere equ 0feh ; Topview active query
tvsynch equ 0ffh ; Topview resynch request
tv_segs dw 0 ; Topview virtual screen, segment
tv_sego dw 0 ; and offset
tv_mode db 0 ; flag, 0 = no Topview or DESQview
savadr dw 2 dup (0) ; offset then segment of saved screen
savflg dw 0 ; low_rgt at time of screen save
att_low_mask equ 06H ; Various attribute-related equates
att_underline equ 01H
att_intensity equ 08H
att_blink equ 80H
att_normal equ 07h
; The following are used to turn the display back on (after scrolling etc.)
msets db 2CH,28H,2DH,29H,2AH,2EH,1EH,29H
vtemu emulst <> ; emulator flags
trmtyp db 0 ; most recent terminal type
mtty db ' TTY ' ; no terminal type (mode line)
belltype db 0 ; 0 = aural bell, 1 = visual
fairness dw 0
fairprn dw 0
lincur dw ? ; cursor type save area
scbattr db ? ; screen background attribute
dosattr db ? ; screen attributes at init time
userbold db 0 ; screen bold attribute at start up
dos_cols db 0 ; screen width (crt_cols) at DOS
savattr db ? ; current emulator attributes
oldsp dw 0 ; offset to longjmp to for i/o failure
ten db 10 ; byte constant for key defines
temp dw 0 ; scratch storage
captrtn dw 0 ; routine to call for captured output
dmphand dw -1 ; screen dump file handle
dumplen equ 132
dumpbuf db dumplen dup (0), cr, lf ; 134 byte dump work buffer
dumpsep db FF,cr,lf ; screen image separators
dmperr db ' Cannot open file to save screen to disk $'
memerr db cr,lf,'Not enough memory for terminal emulator$'
crlf db cr,lf,'$'
flowon db 0 ; flow control chars xon
flowoff db 0 ; and xoff (or both null if none)
pntmsg db 'Printer not ready, printing request skipped$'
upsshlp db cr,lf,'User Preferred Supplemental Set: DEC-MCS or Latin-1$'
; some static data for mode line
modmaster modfrm <> ; master template
modbuf modfrm <> ; mode line buffer
unkbaud db 'unkwn ' ; must be 6 chars
baudn db ' 45.5 ',' 50 ',' 75 ',' 110 ','134.5 ',' 150 ',' 300 '
db ' 600 ',' 1200 ',' 1800 ',' 2000 ',' 2400 ',' 4800 ',' 9600 '
db '19200 ','38400 ','57.6K ','115 K ','75/12 '
baudnsiz equ 19 ; # of baud rates known (tbl size / 4)
repmsg db 'REPLAY' ; REPLAY message for speed field
repmsgl equ $-repmsg
parnams db 'even','mark','none','odd ','spc '
lclmsg db 'loc'
remmsg db 'rem'
portno db 0
; storage for multi-window stuff
swidth equ 80 ; max screen width
slen equ 24 ; and length of text
crt_norm db 3 ; video mode for normal screen
crt_mode db 3 ; video mode (typ 3, must be text)
; keep crt_cols & crt_lins in order
crt_cols db 80 ; number of screen columns (typ 80)
crt_lins db 24 ; number of screen rows - 1 (typ 24)
low_rgt dw 174fh ; lower right corner of text window
; high = row address (typ 23)
; low = column address (typ 79)
inipara dw 0 ; initial paragraphs of scroll memory
refresh db 0 ; screen refresh (0=wait for retrace)
vtroll db 0 ; auto roll back allowed (0 = no)
vtrname db 'TERMINALR' ; a macro name, must be Upper Case
vtrlen equ $-vtrname
vtsname db 'TERMINALS' ; a macro name, must be Upper Case
vtslen equ $-vtsname
prodname db 'PRODUCT'
vtplen equ $-prodname
vtmacname dw vtrname ; pointer to selected macro name
vtmaclen dw vtrlen
udkseg dw 18 dup (0) ; segment of user definable key defs
even ; screen rollback material
iniseg dw ? ; (BDT) initial seg of scroll memory
ppl dw 0 ; (BDT) paragraphs per line
lcnt dw 0 ; (BDT) number of "filled" buffer lines
linef dw 0 ; (BDT) "first" filled line is here
linec dw 0 ; (BDT) "current" screen line number
linee dw 0 ; (BDT) total # of lines in the buffer
lmax dw 0 ; (BDT) max lines in buff (less 1 scrn)
lxtra dw 0 ; (BDT) "extra" lines rqd for screen
setchtab db 6 ; Set File Character-Set table
mkeyw 'CP437',437 ; hardware default Code Page
mkeyw 'CP850',850 ; Multilingual CP
mkeyw 'CP860',860 ; Portuguese CP
mkeyw 'CP863',863 ; French Canadian CP
mkeyw 'CP865',865 ; Norwegian CP
mkeyw 'CP866',866 ; Latin5/Cryillic CP
;; mkeyw 'User-defined',1 ; User loadable table
; begin Terminal emulator data set
termtb db tttypes ; entries for Status, not Set
mkeyw 'VT320',ttvt320
mkeyw 'VT220',ttvt220
mkeyw 'VT102',ttvt102
mkeyw 'VT100',ttvt100
mkeyw 'VT52',ttvt52
mkeyw 'Honeywell VIP7809',tthoney
mkeyw 'Heath-19',ttheath
mkeyw 'Tek4010',tttek
mkeyw 'none',ttgenrc
vttbl db 32 ; number of entries
mkeyw 'Arrow-keys',arkval
mkeyw 'Bell',8800h ; note 8800 flag for decoding
mkeyw 'Bytesize',8900h ; syn for set display 7/8
mkeyw 'Character-set',chaval+8300h
mkeyw 'Clear-screen',8500h ; 8500h = marker here
mkeyw 'Color',8200H ; screen fore/back colors; 200H=marker
mkeyw 'Controls',cntlval
mkeyw 'Cursor-style',curval
mkeyw 'Direction',dirval
mkeyw 'Display',8900h ; syn for set display 7/8
mkeyw 'Graphics',8600h ; Tek graphics board, 800h=marker
mkeyw 'Heath-19',ttheath+8100H; note 8100H flag for decoding here
mkeyw 'Honeywell',tthoney+8100h
mkeyw 'Keyclick',keyval
mkeyw 'Keypad',kpamval
mkeyw 'Margin-bell',marval
mkeyw 'None',ttgenrc+8100H
mkeyw 'Newline',newval
mkeyw 'Replay',8700h ; note 8700H flag for file replaying
mkeyw 'Rollback',8400h ; note 8400H flag for decoding
mkeyw 'Screen-background',scrval
mkeyw 'Tabstops',tabval
mkeyw 'Tek4010',tttek+8100H
mkeyw 'Type',81ffH ; SET TERM TYPE
mkeyw 'VT320',ttvt320+8100H
mkeyw 'VT220',ttvt220+8100H
mkeyw 'VT102',ttvt102+8100H
mkeyw 'VT100',ttvt100+8100h
mkeyw 'VT52',ttvt52+8100H
mkeyw 'UPSS',8A00h ; note 8A00h flag for UPSS
mkeyw 'Width',widthval
mkeyw 'Wrap',wraval
ontab db 2 ; two entries
mkeyw 'off',0
mkeyw 'on',1
beltab db 3 ; bell type
mkeyw 'audible',0
mkeyw 'visual',1
mkeyw 'none',2
distab db 2 ; display
mkeyw '7-bit',0
mkeyw '8-bit',d8bit
scrtab db 2 ; screen attributes
mkeyw 'normal',0
mkeyw 'reverse',1
dirtab db 2 ; writing direction
mkeyw 'left-to-right',0
mkeyw 'right-to-left',1
curtab db 2 ; cursor attributes
mkeyw 'block',0
mkeyw 'underline',1
chatab db 18 ; National Replacement Character sets
mkeyw 'ASCII',0 ; ASCII is default (0, no NRC)
mkeyw 'British',1 ; start NRC set (1-12)
mkeyw 'Dutch',2
mkeyw 'Finnish',3
mkeyw 'French',4
mkeyw 'Fr-Canadian',5
mkeyw 'German',6
mkeyw 'Italian',7
mkeyw 'Norwegian/Danish',8
mkeyw 'Portuguese',9
mkeyw 'Spanish',10
mkeyw 'Swedish',11
mkeyw 'Swiss',12 ; end of NRC proper
mkeyw 'Alternate-ROM',13 ; Alternate-ROM character set
mkeyw 'Transparent',14 ; use native display adapter hardware
mkeyw 'Latin1',15 ; Latin-1 in GR
mkeyw 'DEC-MCS',16 ; DEC Supplemental Graphics in GR
mkeyw 'DEC-Special',18
upsstab db 2
mkeyw 'DEC-MCS',94 ; DEC Supplemental Graphics
mkeyw 'Latin1',96 ; Latin-1
sidetab db 4 ; SET TERM CHAR <char set> Gn
mkeyw 'G0','0'
mkeyw 'G1','1'
mkeyw 'G2','2'
mkeyw 'G3','3'
graftab db 12
mkeyw 'auto-sensing',0 ; autosensing
mkeyw 'CGA',1
mkeyw 'EGA',2
mkeyw 'VGA',3
mkeyw 'Hercules',4
mkeyw 'ATT',5
mkeyw 'WyseA(1280x800)',6 ; Wyse-700 1280 x 800 mode
mkeyw 'WyseH(1280x780)',7 ; Wyse-700 1280 x 780 mode
mkeyw 'WyseT(1024x780)',8 ; Wyse-700 1024 x 780 mode
mkeyw 'character-writing',101h
mkeyw 'color',103h
mkeyw 'cursor',102h
gchrtab db 2 ; set term graphics char-writing
mkeyw 'opaque',1
mkeyw 'transparent',0
disatab db 2 ; Tek disable/enable table
mkeyw 'disable',1
mkeyw 'enable',0
tabtab db 2 ; label says it all!
mkeyw 'at',0FFH ; For setting tab stops
mkeyw 'Clear',0 ; For clearing tab stops
alltab db 2 ; more tab command decoding
mkeyw 'all',0
mkeyw 'at',1
cntltab db 2 ; 8-bit controls
mkeyw '7-bit',0
mkeyw '8-bit',1
kpamtab db 2 ; keypad, application
mkeyw 'Numeric',0
mkeyw 'Application',1
arrtab db 2 ; cursor keys, application
mkeyw 'Cursor',0
mkeyw 'Application',1
widtab db 2
mkeyw '80-columns',0
mkeyw '132-columns',1
vtable dw ontab, ontab, chatab, dirtab ,ontab, ontab, curtab, scrtab
dw cntltab, kpamtab, arrtab, widtab, 0
; which are newline wrap char direct key margin cursor screen
; controls key-app arrow-app width
vtsflg equ this word ; define small digits xxxval
newval equ $-vtsflg ; 0 and mask for bit in byte
dw vsnewline ; 1
wraval equ $-vtsflg ; 2
dw vswrap ; 2
chaval equ $-vtsflg ; 4
dw vsnrcm ; 4
dirval equ $-vtsflg ; 6
dw vswdir ; 8
keyval equ $-vtsflg ; 8
dw vskeyclick ; 10h
marval equ $-vtsflg ; 10
dw vsmarginbell ; 20h
curval equ $-vtsflg ; 12
dw vscursor ; 40h
scrval equ $-vtsflg ; 14
dw vsscreen ; 80h
cntlval equ $-vtsflg ; 16
dw vscntl ; 100h
kpamval equ $-vtsflg ; 18
dw deckpam ; 400h
arkval equ $-vtsflg ; 20
dw decckm ; 200h
widthval equ $-vtsflg ; 22
dw deccol ; 1000h
numflgs equ ($-vtsflg)/2 ; 10
tabval equ $-vtsflg ; 24
dw 0
vtrtns dw numflgs dup (flgset), tabmod ; dispatch table for vtsflg
colortb db 0,4,2,6,1,5,3,7 ; color reversed-bit setting bytes
clrset db 0 ; Temp for SET Term Tabstops xxx
erms41 db cr,lf,'?More parameters are needed$'
vthlp db ' one of the following:',cr,lf
db ' TYPE of: None, Heath-19, Honeywell VIP7809, VT52,'
db ' VT100, VT102,',cr,lf,' VT220, VT320 (default), or Tek4010'
db cr,lf
db ' Newline-mode Cursor-style Character-set'
db cr,lf
db ' Keyclick Margin-bell Screen-background'
db ' (normal, reverse)',cr,lf
db ' Tabstops Wrap (long lines) Color (fore & background)'
db cr,lf,' Arrow-keys cursor (normal) or application mode'
db cr,lf,' Bell audible or visual or none'
db cr,lf,' Clear-screen (clears old startup screen)'
db cr,lf,' Controls 7-bit or 8-bit (permits VT320 to send'
db ' 8-bit control sequences (C1))'
db cr,lf,' Direction Left-to-right or Right-to-left'
db ' (screen writing direction)'
db cr,lf,' Display or Bytesize 7-bit or 8-bit'
db cr,lf,' Graphics (type of display adapter when in Tek4010'
db ' mode, and char writing)'
db cr,lf,' Keypad numeric (normal) or application mode'
db cr,lf,' Replay filespec (display a file through the emulator)'
db cr,lf,' Rollback (undo screen roll back before writing new'
db ' chars, default=off)'
db cr,lf,' TEK ENABLE or DISABLE (activation by host command)'
db cr,lf,' Width 80 or 132 columns, if the adapter can do it$'
clrhlp db ' one of the following:'
db cr,lf,' AT #s (to set tabs at column #s) or'
db ' AT start-column:spacing'
db cr,lf,' Clear AT #s (clears individual tabs) or'
db ' AT start-column:spacing'
db cr,lf,' Clear ALL (to clear all tabstops)'
clrhlp2 db cr,lf,' Ex: Set term tab at 10, 20, 34 sets tabs'
db cr,lf,' Ex: Set term tab at 1:8 sets tabs at 1, 9,'
db cr,lf,' Ex: Set term tab clear at 9, 17, 65 clears tabs'
db cr,lf,' Ex: Set term tab clear at 1:8 clears tabs at 1, 9,'
db ' 17,...$'
tbserr db cr,lf,'?Column number is not in range 1 to screen width-1$'
colhlp db cr,lf,' Set Term Color value, value, value, ...'
db cr,lf,' 0 no-snow mode on an IBM CGA and white on black'
db cr,lf,' 1 for high intensity foreground'
db cr,lf,' 10 for fast CGA screen updating (may cause snow)'
db cr,lf,' Foreground color (30-37) = 30 + sum of colors'
db cr,lf,' Background color (40-47) = 40 + sum of colors'
db cr,lf,' where colors are 1 = red, 2 = green, 4 = blue'
db cr,lf,' Ex: 0, 1, 37, 44 IBM CGA(0), bright(1) white(37)'
db ' chars on a blue(44) field'
db cr,lf,' Attributes are applied in order of appearance.$'
colerr db cr,lf,'?Value not in range of 0, 1, 10, 30-37, or 40-47$'
vtwrap db 'Term wrap-lines: $'
vtbellm db 'Term margin-bell: $'
vtnewln db 'Term newline: $'
vtcur db 'Term cursor-style: $'
vtcset db 'Term character-set: $'
vtclik db 'Term key-click: $'
vtscrn db 'Term screen-background: $'
colst1 db 'Term color foregnd:3$'
colst2 db ' backgnd:4$'
vtgraf db 'Term graphics: $'
vtrolst db 'Term rollback: $'
vtdir db 'Term direction: $'
vtcntst db 'Term controls: $'
vtkpst db 'Term keypad: $'
vtarst db 'Term arrow-keys: $'
vtbset db 'Term bell: $'
vtgchst db 'Term graph char: $'
vtwdst db 'Term width: $'
vtupsst db 'Term UPSS: $'
; terminal emulator
vtstbl stent <srchkw,vtcset,chatab,vtemu.vtchset> ; char set
stent <srchkb,vtclik,ontab,vskeyclick,vtemu.vtflgop> ; keyclick
stent <colstat> ; colors
stent <srchkb,vtwrap,ontab,vswrap,vtemu.vtflgop> ; line wrap
stent <srchkb,vtcntst,cntltab,vscntl,vtemu.vtflgop> ; controls
stent <srchkb,vtbellm,ontab,vsmarginbell,vtemu.vtflgop>;margin bell
stent <srchkb,vtcur,curtab,vscursor,vtemu.vtflgop> ; cursor type
stent <srchkw,vtbset,beltab,belltype> ; bell
stent <srchkb,vtdir,dirtab,vswdir,vtemu.vtflgop> ; write direct
stent <srchkb,vtnewln,ontab,vsnewline,vtemu.vtflgop> ; newline
stent <srchkw,vtgraf,graftab,tekgraf> ; graphics
stent <srchkw,vtrolst,ontab,vtroll> ; rollback
stent <srchkw,vtgchst,gchrtab,chcontrol> ; chr cntrl
stent <srchkb,vtarst,arrtab,decckm,vtemu.vtflgop> ; arrow-keys
stent <srchkb,vtscrn,scrtab,vsscreen,vtemu.vtflgop> ; screen
stent <srchkb,vtkpst,kpamtab,deckpam,vtemu.vtflgop> ; keypad
stent <srchkb,vtwdst,widtab,deccol,vtemu.vtflgop> ; width
stent <srchkw,vtupsst,upsstab,upss> ; UPSS
stent <tabstat> ; VT320 tab status - needs one whole line
dw 0 ; end of table
endconptr dw offset endcon,seg endcon ; FAR pointer
productptr dw offset fproduct,seg fproduct ; FAR pointer
vtmacroptr dw offset vtmacro,seg vtmacro ; FAR pointer
fxgaman dw offset xgaman,seg xgaman ; FAR pointer
data ends
; end of Terminal data set
code2 segment
extrn tekini:far,tekemu:far,tekend:far,tekrint:far ;in msgibm
code2 ends
code segment
extrn prtchr:near, outchr:near, sbrk:near, pcwait:near
extrn isfile:near ; in mssfil
extrn anstty:near,ansini:near,ansrei:near ; in mszibm
extrn anskbi:near,ansdsl:near ; in mszibm
extrn ans52t:near, vsinit:near ; in mszibm
extrn msuinit:near, keybd:near, kbhold:near ; in msuibm
extrn clrmod:near, putmod:near, cmblnk:near
extrn telnet:near, tabset:near, tabclr:near, istabs:near
extrn atoi:near, strlen:near, srchkb:near, srchkw:near, pasz:near
extrn prompt:near, comnd:near, statc:near, replay:near
extrn crun:near, serini:near, spath:near, strcpy:near, tekdmp:near
extrn prttab:near, dec2di:near, tekgcptr:near
extrn pntchr:near, pntflsh:near
extrn decout:near
assume cs:code, ds:data, es:nothing
fscrmod proc FAR
call scrmod
ret
fscrmod endp
fscrseg proc FAR
call scrseg
ret
fscrseg endp
fscroff proc FAR
call scroff
ret
fscroff endp
fscron proc FAR
call scron
ret
fscron endp
fscrsync proc FAR
call scrsync
ret
fscrsync endp
fatsclr proc FAR
call atsclr
ret
fatsclr endp
fisfile proc FAR
call isfile
ret
fisfile endp
fgetpos proc FAR
call getpos
ret
fgetpos endp
fsetpos proc FAR
call setpos
ret
fsetpos endp
code ends
code1 segment
assume cs:code1
; Save the entire screen in a buffer so we can restore and/or dump it.
; Saves regular (80x25) screens to memory buffer allocated dynamically from
; DOS or if insufficient space then to video memory page 1. Save address is
; savadr+2:savadr (seg:offset). A memory buffer is deallocated and reallocated
; if it's size needs to change, otherwise it is reused as is.
; Current crt_cols & crt_lins size info is saved in savflg for restscr. Note,
; some Environments (TopView/Windows etc) may not permit use of page 1 and we
; will not save the screen if video page 1 is required under Environments.
fsavescr proc FAR
push es
push ds
push ax
push cx
push dx
push si
push di
call fscrmod ; ascertain video mode and screen
call fscrseg ; get screen segment in ax and es:di
mov di,ax ; save screen seg in di
mov ax,word ptr crt_cols ; text screen lower right (typ 80,24)
inc ah ; plus status line = number of rows
mul ah ; times rows = characters on screen
shl ax,1 ; times two for attributes = page 1
mov dx,ax ; save number of screen bytes in dx
mov ax,savadr+2 ; seg of saved memory, if any
or ax,ax ; none?
jz savsc1 ; z = yes, none
cmp ax,0a000h ; in video memory?
jae savsc1 ; ae = yes
mov ax,word ptr crt_cols ; text screen lower right (typ 80,24)
cmp ax,savflg ; same as saved screen?
je savsc4 ; e = yes, no allocation needed
mov savflg,ax
mov ax,savadr+2 ; get old allocation
mov es,ax
mov ah,freemem ; free old memory
int dos
mov savadr+2,0 ; clear old segment
; allocate and use DOS memory for save
savsc1: mov bx,dx ; bytes to do
add bx,15 ; round up
mov cl,4
shr bx,cl ; bytes/screen to paragraphs/screen
mov ah,alloc ; allocate memory
int dos ; bx has # free paragraphs
jc savsc2 ; c = not enough for it, use video
mov savadr+2,ax ; working seg address for restore
mov savadr,0 ; and no offset for memory buffer
jmp short savsc4
; use video page 1 as save area
savsc2: cmp di,0a000h ; screen segment is in DOS (Environ)?
jae savsc3 ; ae = no
mov savadr+2,0 ; then say no seg because no save
jmp savsc5 ; exit without saving screen
savsc3: mov cx,dx ; number of screen bytes
and cx,000fh ; get lower four bits for offset part
mov savadr,cx ; save offset in this word
mov ax,dx ; number of screen bytes
mov cl,4
shr ax,cl ; compute number of paragraphs
add ax,di ; add paragraphs, point ax to page 1
mov savadr+2,ax ; and save segment in this word
; save the screen
savsc4: push word ptr crt_cols ; current screen dimensions
pop savflg ; save it for screen restore
mov cx,dx ; number of screen bytes
shr cx,1 ; do as words
push di ; preserve di around call
call fscroff ; turn off screen [dt]
pop di
mov ax,savadr+2 ; destination segment
mov es,ax ; segment of storage area
push di ; screen memory segment from di
mov di,savadr ; offset of storage
pop ds ; put into ds
xor si,si
cld
rep movsw ; save the screen
savsc5: pop di
pop si
pop dx
pop cx
pop ax
pop ds
call fscron ; turn on screen
pop es
ret
fsavescr endp
; Restore screen from buffer (savadr+2:savadr, with screen size in savflg).
; Restores all screen lines.
frestscr proc FAR
push es
push si
push di
cmp savadr+2,0 ; saved anything yet?
jne restsc1 ; ne = yes
call fscrmod ; get current screen size
xor ax,ax
mov bx,word ptr crt_cols ; clear the screen to current colors
dec bl ; count columns from 0
call fatsclr
jmp short restsc2
restsc1:mov ax,savflg ; saved low_rgt text screen coord
inc ah ; number of screen rows
mul ah ; columns time lines = # characters
mov cx,ax ; save this in counter cx
push cx ; save count
call fscrseg ; get address of screen in es:di
call fscroff ; turn off screen [dt]
push ds ; save original data segment
mov si,savadr ; offset of storage area
push savadr+2 ; segment of same
pop ds ; put storage segment into ds
cld
rep movsw ; restore data to screen
pop ds ; recover original data segment
call fscron ; turn on screen [dt]
pop cx ; recover count
call fscrsync ; synch Topview with new screen
restsc2:pop di
pop si
pop es
ret
frestscr endp
; Save the screen to a buffer and then append buffer to a disk file. [jrd]
; Default filename is Kermit.scn; actual file can be a device too. Filename
; is determined by mssset and is passed as pointer dmpname.
; Dumpscr reads the screen image saved by savescr so call savescr call first.
fdumpscr proc FAR
cmp savadr+2,0 ; any save area?
jne dmp6 ; ne = yes
clc ; else ignore and return success
ret
dmp6: push ax
push bx
push cx
push dx
mov dmphand,-1 ; preset illegal handle
mov dx,offset dmpname ; name of disk file, from mssset
mov ax,dx ; where isfile wants name ptr
call fisfile ; what kind of file is this?
jc dmp5 ; c = no such file, create it
test byte ptr filtst.dta+21,1fh ; file attributes, ok to write?
jnz dmp0 ; nz = no.
mov al,1 ; writing
mov ah,open2 ; open existing file
int dos
jc dmp0 ; c = failure
mov dmphand,ax ; save file handle
mov bx,ax ; need handle here
mov cx,0ffffh ; setup file pointer
mov dx,-1 ; and offset
mov al,2 ; move to eof minus one byte
mov ah,lseek ; seek the end
int dos
jmp dmp1
dmp5: test filtst.fstat,80h ; access problem?
jnz dmp0 ; nz = yes
mov ah,creat2 ; file did not exist
mov cx,20h ; attributes, archive bit
int dos
mov dmphand,ax ; save file handle
jnc dmp1 ; nc = ok
dmp0: call fgetpos ; get cursor position
push dx ; save it
mov dh,byte ptr low_rgt+1 ; go to status line
inc dh
xor dl,dl ; left most column
call fsetpos ; position cursor
mov dx,offset dmperr ; say no can do
mov ah,prstr
int dos
pop dx ; get original cursor position
call fsetpos ; position cursor
pop dx
pop cx
pop bx
pop ax
clc
ret
dmp1: mov ah,ioctl ; is destination ready for output?
mov al,7 ; test output status
mov bx,dmphand ; handle
int dos
jc dmp0 ; c = error
cmp al,0ffh ; ready?
jne dmp0 ; ne = not ready
push di ; read screen buffer, write lines
push si
push es
mov cl,byte ptr low_rgt+1 ; number of lines - 2
add cl,2 ; number of line on screen
xor ch,ch
mov si,savadr ; offset in storage area
dmp2: push cx ; save outer loop counter
mov es,savadr+2 ; get storage segment
mov di,offset dumpbuf ; data segment memory
mov cl,byte ptr savflg ; number of columns on screen
xor ch,ch
dmp3: mov ax,word ptr es:[si] ; read char + attribute
or al,al ; is it a null?
jnz dmp3c ; nz = no
mov al,' ' ; replace null with space
dmp3c: mov byte ptr [di],al ; store just char, don't use es:
inc si ; update pointers
inc si
inc di
loop dmp3 ; do for each column
std ; set scan backward
mov cl,byte ptr savflg ; number of columns on screen
xor ch,ch
push es
mov ax,ds
mov es,ax ; set es to data segment for es:di
mov di,offset dumpbuf ; start of line
add di,cx ; plus length of line
dec di ; minus 1 equals end of line
mov al,' ' ; thing to scan over
repe scasb ; scan until non-space
cld ; set direction forward
pop es
jz dmp3a ; z = all spaces
inc cx
inc di
dmp3a: mov word ptr [di+1],0A0Dh ; append cr/lf
add cx,2 ; line count + cr/lf
mov dx,offset dumpbuf ; array to be written
mov bx,dmphand ; need file handle
mov ah,write2 ; write the line
int dos
pop cx ; get line counter again
jc dmp3b ; c = error
loop dmp2 ; do next line
mov dx,offset dumpsep ; put in formfeed/cr/lf
mov cx,3 ; three bytes overall
mov ah,write2 ; write them
dmp3b: mov bx,dmphand ; file handle
int dos
mov ah,close2 ; close the file now
int dos
pop es
pop si
pop di
pop dx
pop cx
pop bx
pop ax
clc
ret
fdumpscr endp
code1 ends
code segment
assume cs:code
dumpscr proc near
call fdumpscr
ret
dumpscr endp
savescr proc near
call fsavescr
ret
savescr endp
restscr proc near
call frestscr
ret
restscr endp
; do initialization local to this module
; Dynamically allocates 4000 bytes for screen save/restore buffer plus
; 320 to 38400 bytes for screen scroll back buffers. Tries to leave space
; for Command.com before enlarging buffers. [jrd]
lclyini proc near
call msuinit ; initialize keyboard module msuxxx
mov ah,conout ; write a space to determine
mov dl,' ' ; DOS's default cursor coloring
int dos
call getpos ; get current cursor position into dx
mov lincur,cx ; save cursor type (scan line #'s)
dec dl ; backup to last char
or dl,dl
jns lclyin5 ; ns = no problem
xor dl,dl ; else set cursor back to left margin
lclyin5:call setpos ; set cursor position
call getatch ; read current attributes into AH
mov scbattr,ah ; save video attributes
mov savattr,ah ; and saved attributes
mov dosattr,ah ; and here too
and ah,att_intensity ; select intensity bit
mov userbold,ah ; save bit for user Bold control
mov ega_mode,0 ; assume no EGA
mov ax,1200H ; EGA: Bios alternate select
mov bl,10H ; Ask for EGA info
mov bh,0ffH ; Bad info, for testing
mov cl,0fH ; Reserved switch settings
int screen ; EGA, are you there?
cmp cl,0cH ; Test reserved switch settings
jge lclyin1 ; ge = no EGA in use
push es
mov ax,40h ; check Bios 40:87h for ega being
mov es,ax ; the active display adapter
test byte ptr es:[87h],8 ; is ega active?
pop es
jnz lclyin1 ; nz = no
mov ega_mode,1 ; yes, set flag to say so
mov crt_norm,3 ; assume color monitor is attached
or bh,bh ; is color mode in effect?
jz lclyin1 ; z = yes
mov crt_norm,7 ; else use mode 7 for mono
lclyin1:call scrseg ; test running in an Environment
call dvtest ; test for running under DESQview
call scrmod ; read video state, get crt_mode
mov ax,low_rgt ; lower right corner of screen
mov al,crt_mode
mov crt_norm,al ; save as normal mode
; screen roll back buffers
mov al,crt_lins ; physical length of user area
mul crt_cols ; physical width
add ax,7 ; round up
mov cl,3
shr ax,cl ; bytes/screen to paragraphs/screen
mov si,ax ; save a copy in si
mov bx,npages ; number of roll back screens wanted
inc bx ; include current screen in count
mul bx ; total number of screens wanted
mov cx,ax ; save total wanted paragraphs in cx
mov bx,0ffffh ; ask for all of memory, to get size
mov ah,alloc ; allocate all of memory (must fail)
int dos ; bx has # free paragraphs
mov ax,bx ; ax has copy of number free paragraphs
sub bx,26000D/16 ; space for Command.com copy #2
jc lclyin2 ; c = not enough for it
cmp bx,si ; minimum roll back space left over?
jbe lclyin2 ; be = not even that much
cmp bx,cx ; got vs wanted paras for roll back
jbe lclyin3 ; be = enough but not more than needed
mov bx,cx ; limit to our actual needs
jmp short lclyin3 ; ask for all we really want
lclyin2:xor bx,bx ; use no space at all
mov cx,bx ; remember this new request
lclyin3:mov ah,alloc
int dos
mov iniseg,ax ; (BDT) memory segment, window area
mov inipara,bx ; save for later resizing of buffers
cmp cx,bx ; paragraphs wanted vs delivered
jae lclyin4 ; ae = enough
mov ah,prstr
mov dx,offset memerr ; say not enough memory to operate
int dos
mov flags.extflg,1 ; set Kermit exit flag
lclyin4:call bufadj ; set roll back buffer parameters
call vsinit ; init terminal emulator module MSZ
mov bx,vtemu.att_ptr ; attributes pointer
mov ah,dosattr ; startup video attributes
and ah,not att_intensity ; emulation intensity to normal
or ah,userbold
mov [bx],ah ; set initial emulation attributes
and vtemu.vtflgst,not deccol ; assume 80 column screen
and vtemu.vtflgop,not deccol
cmp crt_cols,80 ; screen cols now, wide screen?
jbe lclyin6 ; be = no
or vtemu.vtflgst,deccol ; say using 132 columns screen
or vtemu.vtflgop,deccol
lclyin6:ret
lclyini endp
; Determine screen roll back buffer parameters depending on current screen
; dimensions and available memory. Each rollback screen line has its own
; segment (lines start on segment boundaries for rollback).
bufadj proc near
push bx
push cx
push dx
mov lxtra,0 ; assume no storage for "extra" lines
xor bh,bh ; (BDT) get bytes / line
mov bl,crt_cols ; (BDT) physical line width
add bx,7 ; (BDT) round up to paragraph boundary
mov cl,3 ; (BDT) now convert to
shr bx,cl ; (BDT) paragraphs / line
mov ppl,bx ; (BDT) save this in buffer area
mov ax,inipara ; (BDT) compute the number of lines
xor dx,dx
div bx ; (BDT) in the buffer
mov lmax,ax ; max line capacity of the buffer
mov linee,ax ; (BDT) save as number of total lines
or ax,ax ; is this zero?
jz bufadj1 ; z = yes, no space at all
xor bh,bh ; (BDT) get lines / screen
mov bl,byte ptr low_rgt+1 ; (BDT) rows on user/host screen
inc bx ; (BDT) adjust for counting from 0
mov lxtra,bx ; (BDT) save as "extra" lines
sub lmax,bx ; (BDT) deduct "extra" lines req'd
jg bufadj1 ; g = have some rollback space
mov lmax,0 ; say none
mov lxtra,0 ; say none of these too
bufadj1:mov lcnt,0 ; (BDT) # of lines filled in buffer
mov linef,0 ; (BDT) first filled in line
mov linec,0 ; (BDT) last filled in line
pop dx
pop cx
pop bx
ret
bufadj endp
; begin Terminal set & status code
; SET Term parameters, especially for use with VT100 emulator. [jrd]
; Taken from work done originally by James Harvey IUPUI.
; VTS is called only by mssset to set terminal type and characteristics.
; Enter via direct jmp. Exit carry set for failure.
VTS proc near ; SET TERM whatever
mov ah,cmkey ; Parse another keyword
mov bx,offset vthlp ; Use this help
mov dx,offset vttbl ; Use this table
call comnd
jnc vset1 ; nc = success
ret ; failure
vset1: cmp bh,81H ; marker for terminal type?
je vsetu0 ; e = yes
cmp bh,82h ; marker for set term color?
jne vset1a ; ne = no
jmp vsetu2 ; e = yes
vset1a: cmp bh,83h ; marker for character set?
jne vset1f ; ne = no
jmp vsetu3 ; e = yes
vset1f: cmp bh,84h ; marker for roll back control?
jne vset1g ; ne = no
jmp vsetu4 ; e = yes
vset1g: cmp bh,85h ; marker for clear-screen?
jne vset1b ; ne = no
mov ah,cmeol ; yes
call comnd
jc vset1h ; c = failure
mov vtclear,2 ; set trigger for emulator clear scn
clc ; success
vset1h: ret
vset1b: cmp bh,86h ; marker for graphics type?
jne vset1c ; ne = no
jmp vsetu8 ; yes
vset1c: cmp bh,87h ; marker for REPLAY?
jne vset1d ; ne = no
jmp REPLAY ; yes, do REPLAY
vset1d: cmp bh,88h ; marker for BELL?
jne vset1i ; ne = no
jmp vsetu10 ; yes, do BELL setup
vset1i: cmp bh,89h ; SET TERM DISPLAY / BYTESIZE?
jne vset1j ; ne = no
jmp vsetu11 ; do command
vset1j: cmp bh,8Ah ; SET TERM UPSS?
jne vsetu1 ; ne = no
jmp vsetu12
vsetu1: jmp vtrtns[bx] ; Dispatch
vsetu0: cmp bx,81ffh ; just SET TERM TYPE?
jb vsetu0f ; b = no, have kind
mov ah,cmkey ; parse another keyword
xor bx,bx ; table is help
mov dx,offset termtb ; use this table
call comnd
jnc vsetu0f ; nc = success
ret ; failure
vsetu0f:mov byte ptr temp,bl ; set terminal type
mov byte ptr temp+1,-1 ; assume no enable/disable Tek
cmp bl,tttek ; set term tek?
jne vsetu0a ; ne = no
mov dx,offset disatab ; disable/enable keyword table
xor bx,bx ; help is the table
mov comand.cmcr,1 ; allow bare CR's
mov ah,cmkey ; get enable/disable keyword
call comnd
mov comand.cmcr,0 ; no more bare CR's
jc vsetu0e ; c = no such keyword
mov byte ptr temp+1,bl ; save enable/disable keyword value
mov bl,flags.vtflg ; get current terminal type
mov byte ptr temp,bl ; and force it here
vsetu0a:mov ah,cmeol
call comnd ; get a confirm
jc vsetu0d ; c = failure
vsetu0e:mov bx,temp
mov flags.vtflg,bl ; Set the terminal emulation type
mov tekflg,0 ; clear Tek sub mode
cmp bl,tttek ; adjusting Tek?
je vsetu0b ; e = yes
cmp bh,-1 ; just enable/disable tek?
je vsetu0c ; e = no
vsetu0b:and denyflg,not tekxflg ; enable Tek
cmp bh,1 ; ought we disable?
jne vsetu0c ; ne = no
or denyflg,tekxflg ; disable Tek
vsetu0c:clc ; success
vsetu0d:ret
vsetu3: mov ah,cmkey ; Set Term character set
xor bx,bx ; character set table for help
mov temp,bx ; counter of trailing items
mov dx,offset chatab ; character set table
call comnd
jc vsetu0d ; c = failure
mov dumpbuf,bl ; save here
mov ax,word ptr vtemu.vttable ; table of 4 overrides now
mov word ptr dumpbuf+1,ax ; copy them to temporary table
mov ax,word ptr vtemu.vttable+2
mov word ptr dumpbuf+3,ax
vsetu3a:mov comand.cmcr,1 ; allow bare CR's
mov ah,cmkey
xor bx,bx
mov dx,offset sidetab ; read Gnumber item, if any
call comnd
mov comand.cmcr,0 ; no bare CR's
jc vsetu3b ; c = no match, get confirm
inc temp ; say have a trailing table number
and bx,3 ; remove value encoding
add bx,offset dumpbuf+1 ; address of slot to store info
mov al,dumpbuf ; set ident
mov [bx],al ; store table ident in G0..G3 slot
jmp short vsetu3a ; repeat
; vtemu.vtchset: changed to new set if no table trailers, else intact
; vtemu.vttable db 4 dup(0ffh) char set numbers for G0..G3 as overrides,
; use 0ffh to mean no override for table Gn
vsetu3b:mov ah,cmeol ; get EOL confirmation
call comnd
jc vsetu3d ; c = failure, quit
mov vtemu.vtchop,0ffh ; say reinit char tables
cmp temp,0 ; trailers (skip regular setup)?
jne vsetu3c ; ne = yes
mov al,dumpbuf ; get character set
mov vtemu.vtchset,al ; set default character set
; just overrides
vsetu3c:mov ax,word ptr dumpbuf+1 ; first pair of char set idents
mov word ptr vtemu.vttable,ax
mov ax,word ptr dumpbuf+3 ; second pair
mov word ptr vtemu.vttable+2,ax
clc
vsetu3d:ret
vsetu4: mov ah,cmkey ; Set Term Roll On/Off, auto roll back
xor bx,bx ; Use on/off table as help
mov dx,offset ontab ; Use on/off table
call comnd
jc vsetu4a ; c = failure
mov temp,bx
mov ah,cmeol ; get a confirm
call comnd
jc vsetu4a ; c = failure
mov bx,temp
mov vtroll,bl ; set roll state (0=no auto rollback)
clc
vsetu4a:ret
; Set Term Color foreground, background
vsetu2: mov bx,vtemu.att_ptr ; get address of attributes byte
mov bl,[bx] ; get attributes
mov dumpbuf,bl ; save in work temp
mov al,vtclear ; screen clear state
mov ah,refresh ; refresh state
mov word ptr dumpbuf+1,ax ; save here
call vsetcol ; get and analyze colors
jc vsetu2a ; c = failure
mov al,dumpbuf ; get current attributes
mov bx,vtemu.att_ptr ; get address of attributes byte
mov [bx],al ; store attributes
mov ax,word ptr dumpbuf+1
mov vtclear,al ; update these items
mov refresh,ah
clc
vsetu2a:ret
; setup color information
vsetcol:mov ah,cmword ; get number(s) after set term color
mov bx,offset colhlp ; use this help
mov dx,offset rdbuf ; temp buffer
mov rdbuf,0 ; clear the buffer
mov comand.cmcr,1 ; allow bare c/r's
call comnd
jc vsetco2 ; c = failure
or ax,ax ; text given?
jz vsetco1 ; z = no
mov si,offset rdbuf ; si = place where atoi wants text
call vsetco3 ; analyze
jmp short vsetcol ; get more data
vsetco1:mov ah,cmeol ; get end of line confirm
call comnd
vsetco2:ret ; c set if failure
vsetco3:mov dx,si
call strlen ; get count for atoi
mov ah,cl ; count for atoi
call atoi ; convert text to numeric in ax
jnc vsetco3a ; got a value
ret ; out of data
vsetco3a:or ax,ax ; reset all? regular IBM CGA refresh
jnz vsetco4 ; nz = no
mov dumpbuf+2,0 ; Regular (slow) screen refresh
mov dumpbuf,07h ; clear all, set white on black
mov dumpbuf+1,2 ; set trigger for emulator clear scrn
jmp short vsetco3
vsetco4:cmp ax,1 ; high intensity?
jne vsetco5 ; e = no
or dumpbuf,08h ; set high intensity
mov dumpbuf+1,1 ; set trigger for emulator keep screen
jmp short vsetco3
vsetco5:cmp ax,10 ; fast refresh?
jne vsetco6 ; ne = no
mov dumpbuf+2,1 ; Fast screen refresh
jmp short vsetco3
vsetco6:cmp ax,30 ; check range
jb vsetco8 ; b = too small, complain
cmp ax,37
ja vsetco7 ; 30-37 is foreground color
sub al,30 ; remove foreground bias
and dumpbuf,not 07H ; clear foreground bits
mov bx,ax
mov al,colortb[bx] ; get reversed bit pattern
or dumpbuf,al ; load new bits
mov dumpbuf+1,2 ; set trigger for emulator clear scn
jmp short vsetco3
vsetco7:cmp ax,40
jb vsetco8 ; b = bad value
cmp ax,47 ; compare as unsigned
ja vsetco8 ; 40-47 is background
sub al,40 ; remove background bias
and dumpbuf,not 70H ; clear background bits
mov bx,ax
mov al,colortb[bx] ; get reversed bit pattern
mov cl,4 ; rotate 4 positions
rol al,cl
or dumpbuf,al ; load new bits
mov dumpbuf+1,2 ; set trigger for emulator clear scn
jmp vsetco3
vsetco8:mov ah,prstr ; not in range - complain and exit
mov dx,offset colerr
int dos
stc ; error
ret
vsetu8: mov ah,cmkey ; Set Term graphics
xor bx,bx ; Use graphics table as help
mov dx,offset graftab ; Use graphics table
call comnd
jc vsetu8a ; c = failure
mov temp,bx
cmp bx,100h ; in the special options area?
ja vsetu8b ; a = yes
mov ah,cmeol ; get a confirm
call comnd
jc vsetu8a ; c = failure
mov bx,temp
mov tekgraf,bl ; set Tek graphics board type
clc
vsetu8a:ret
vsetu8b:cmp bx,101h ; character writing?
jne vsetu8c
mov ah,cmkey ; Set Term graphics char-writing
xor bx,bx ; no help
mov dx,offset gchrtab ; opaque/transparent table
call comnd
jc vsetu8a ; c = failure
push bx
mov ah,cmeol ; get a confirm
call comnd
pop bx
jc vsetu8a
mov chcontrol,bl ; set/reset opaque char control
clc
ret
vsetu8c:cmp bx,102h ; cursor on/off?
jne vsetu8e ; ne = no
mov ah,cmkey ; Set Term graphics cursor on/off
xor bx,bx ; no help
mov dx,offset ontab ; on/off table
call comnd
jc vsetu8d ; c = failure
push bx
mov ah,cmeol ; get a confirm
call comnd
pop bx
jc vsetu8d
mov tekcursor,bl ; set Tek text cursor on/off
clc
vsetu8d:ret
vsetu8e:cmp bx,103h ; Color?
jne vsetu8d ; ne = no
call tekgcptr ; get pointer to active Tek color pal
mov al,[bx] ; get background attributes
and al,7 ; discard intensity bit
mov cl,4
shl al,cl
mov ah,[bx+7] ; get foreground attributes
or al,ah
mov dumpbuf,al ; setup work temp for vsetcol
push bx ; save index
call vsetcol ; get and analyze colors
pop bx
jnc vsetu8f ; nc = ok
ret
vsetu8f:mov al,dumpbuf ; get current attributes
mov ah,al ; get background bits
mov cl,4
shr ah,cl ; just background here
and al,0fh ; just foreground here
mov [bx],ah ; store colpal[0] as background
mov [bx+7],al ; store colpal[7] as foreground
clc ; success
ret
vsetu10:mov ah,cmkey ; SET TERM BELL
xor bx,bx ; use table as help
mov dx,offset beltab ; use Bell table
call comnd
jc vsetu10a ; c = failure
mov temp,bx
mov ah,cmeol ; get a confirm
call comnd
jc vsetu10a ; c = failure
mov bx,temp
mov belltype,bl ; set bell type
vsetu10a:ret ; return carry clear or set
; SET TERM BYTESIZE {7-bit | 8-bit}
vsetu11:mov ah,cmkey ; SET TERM DISPLAY {7-bit | 8-bit}
mov dx,offset distab ; table
xor bx,bx ; help is table
call comnd
jc vsetu11a ; c = failure
push bx
mov ah,cmeol ; get a confirm
call comnd
pop bx
jc vsetu11a ; c = failure
and flags.remflg,not d8bit ; clear display 8-bit bit
or flags.remflg,bl ; set or clear the bit
vsetu11a:ret
vsetu12:mov ah,cmkey ; SET TERM UPSS
mov bx,offset upsshlp ; help
mov dx,offset upsstab ; UPSS table
call comnd ; get UPSS char set
jc vsetu12b ; failure
push bx
mov ah,cmeol
call comnd
pop bx
jc vsetu12b ; c = fail
mov ax,'5%' ; assume DEC Supplemental Graphics/94
cmp bx,94 ; Dec Supp Graphics?
je vsetu12a ; ne = no
mov ax,'A' ; Latin-1
vsetu12a:mov upss,bl ; set length
mov word ptr upss+1,ax ; store set ident
mov vtemu.vtchop,0 ; clear operational char set to reinit
clc
vsetu12b:ret
; SET Term flags. These are the (near) equivalent of VT100 Setup mode values.
flgset: push bx ; save index (newval etc)
mov ah,cmkey ; Another keyword
mov dx,vtable[bx] ; The table to use
xor bx,bx ; Use default help
call comnd
mov temp,bx ; save switch value
pop bx ; recover index
jc flgse0 ; c = failure
push bx
mov ah,cmeol ; get confirm
call comnd
pop bx
jc flgse0 ; c = failure
mov dx,temp ; Restore switch value
mov ax,vtsflg[bx] ; get the flag
or dx,dx ; set or clear?
je flgse1 ; e = clear it
or vtemu.vtflgst,ax ; set the flag
or vtemu.vtflgop,ax ; in runtime flags too
flgse3: test ax,deccol ; modifying screen width?
jz flgse2 ; z = no
mov al,crt_cols ; current width
mov dos_cols,al ; width to remember, for changes
flgse2: clc ; success
flgse0: ret
flgse1: not ax ; Complement
and vtemu.vtflgst,ax ; clear the indicated setup flag
and vtemu.vtflgop,ax ; clear the indicated runtime flag
not ax
jmp short flgse3 ; test for screen change
; SET Term Tabstops Clear ALL
; SET Term Tabstops Clear AT n1, n2, ..., nx
; SET Term Tabstops At n1, n2, ..., nx
tabmod: mov ah,cmkey ; parse keyword
mov bx,offset clrhlp ; help text
mov dx,offset tabtab ; table
call comnd
jc tabmo2 ; c = failure
mov clrset,2 ; 2 = code for set a tab
or bl,bl ; clear?
jnz tabmo4 ; nz = no, SET. parse column number(s)
mov clrset,1 ; code for clear at/all tab(s)
mov ah,cmkey ; CLEAR, parse ALL or AT
mov bx,offset clrhlp ; help text
mov dx,offset alltab ; parse ALL or AT
call comnd
jc tabmo2 ; c = failure
or bx,bx ; ALL?
jnz tabmo4 ; nz = AT, clear at specific places
mov ah,cmeol ; confirm the ALL
call comnd
jc tabmo2 ; c = failure
mov cx,132 ; ALL, means clear all tab stops
tabmo1: mov dx,cx
dec dl ; column number, starting with 0
mov si,vtemu.vttbs ; the cold-start buffer
call tabclr ; clear the tab
loop tabmo1 ; do all columns
mov si,vtemu.vttbs
mov di,vtemu.vttbst ; and active buffer
call tabcpy ; update active tabs
clc ; success
tabmo2: ret ; a success/fail return point
tabmo4: mov si,vtemu.vttbs ; from the cold-start buffer
mov di,offset decbuf ; temp work buffer
call tabcpy ; make a working copy of the tabs
mov skip,0 ; clear spacing-active flag
mov temp,0 ; place where last tab was written
tabmo6: mov bx,offset clrhlp2 ; tell them we want a column number
mov ah,cmword ; get line of text
mov dx,offset rdbuf ; temp buffer
call comnd
jc tabmo2 ; c = failure
or ax,ax ; anything given?
jnz tabmo7 ; nz = yes
mov ah,cmeol ; confirm end of line
call comnd
jc tabmo2 ; failure
mov si,offset decbuf ; copy tabs from temp work buffer
mov di,vtemu.vttbs ; to the cold-start buffer
call tabcpy ; copy work to cold start
mov di,vtemu.vttbst ; and terminal emulator's active buf
call tabcpy
clc
ret
tbsbad: mov ah,prstr ; not in range - complain
mov dx,offset tbserr
int dos
stc
ret
tabmo7: mov si,offset rdbuf ; si = place where atoi wants text
tabmo8: mov dx,si
call strlen ; get length of this word
jcxz tabmo6 ; empty, get more user input
mov ah,cl ; where atoi wants length
call atoi ; convert text to numeric in ax
jnc tabmo9 ; nc = successful
cmp byte ptr [si],':' ; spacing separator?
jne tbsbad ; ne = no, no number available
inc si ; skip colon, do start:space analysis
inc skip ; set spacing-active flag
jmp short tabmo8 ; get another token
tabmo9: cmp skip,0 ; want spacing value now?
jne tabmo11 ; ne = yes, go do it
mov dx,ax ; column (1-132 style)
dec dx ; put column in range 0-131
or dx,dx ; check range (1-132 --> 0-131)
jl tbsbad ; l = too small. complain
cmp dl,132-1 ; more than the right most column?
ja tbsbad ; a = yes, quit
mov temp,dx ; remember last written position
jmp tabmo15 ; and write this member
tabmo11:mov dx,temp ; continue spacing analysis
mov skip,0 ; clear spacing-active flag
mov cx,ax ; "space" value
or cx,cx ; zero spacing?
jnz tabmo12 ; nz = no
inc cx ; don't get caught with zero spacing
tabmo12:cmp dx,132-1 ; largest tab stop
ja tabmo8 ; a = done largest tab stop
mov temp,dx ; remember last written tabstop
push si
mov si,offset decbuf ; the work buffer
cmp clrset,2 ; set?
jne tabmo13 ; ne = no, clear
call tabset ; set tabstop in column DL
jmp short tabmo14
tabmo13:call tabclr ; clear tabstop in column DL
tabmo14:add dx,cx ; new column value
pop si
jmp short tabmo12 ; finish spacing loop
tabmo15:push si ; individual tabstop
mov si,offset decbuf ; the work buffer
cmp clrset,2 ; set?
jne tabmo16 ; ne = no, clear
call tabset ; set tabstop in column DL
jmp short tabmo17 ; get next command value
tabmo16:call tabclr ; clear tabstop in column DL
tabmo17:pop si
jmp tabmo8 ; get next command value
tabcpy: push es ; worker copy routine
push si
push di
mov cx,ds
mov es,cx
mov cx,(132+7)/8 ; update all active tab stops
cld
rep movsb
pop di
pop si
pop es
clc ; success
ret
VTS endp ; end of Set Term things
; Terminal Status display, called within STAT0: in MSSSET
VTSTAT proc near ; enter with di within sttbuf, save bx
mov bx,offset vtstbl ; table of things to show
jmp statc ; status common code, in mssset
colstat proc near ; foreground/background color status
push si
mov si,offset colst1
cld
colstd1:lodsb
cmp al,'$' ; end of string?
je colstd2 ; e = yes
stosb
jmp short colstd1
colstd2:mov bx,vtemu.att_ptr ; pointer to attributes byte
mov bl,byte ptr[bx]
xor bh,bh
push bx
and bx,7 ; get foreground set
mov al,colortb[bx] ; get reversed bit pattern
add al,'0' ; add ascii bias
stosb
pop bx
mov si,offset colst2
colstd3:lodsb
cmp al,'$'
je colstd4
stosb
jmp short colstd3
colstd4:mov cl,4 ; rotate 4 positions
shr bl,cl
and bx,7 ; get background set
mov al,colortb[bx] ; get reversed bit pattern
add al,'0' ; add ascii bias
stosb
pop si
ret
colstat endp
; Tabs Status display
tabstat proc near ; display tabs ruler for Status
push dx
cld
mov al,cr
stosb
cmp cl,10 ; are we on a new line?
jb tabsta0 ; b = no, do a lf now
mov al,lf
stosb
tabsta0:xor cl,cl ; column index
xor ax,ax ; ah = tens, al = units counter
tabsta1:mov dl,'.' ; default position symbol
inc al
cmp al,10 ; time to roll over?
jb tabsta2 ; b = not yet
xor al,al ; modulo 10
inc ah
mov dl,ah ; display a tens-digit
add dl,'0'
cmp dl,'9' ; larger than 90?
jbe tabsta2 ; be = no
sub dl,10 ; roll over to 0, 1, etc
tabsta2:push dx
push si
mov dl,cl ; column number, counted from 0
mov si,vtemu.vttbst ; the active buffer
call istabs ; is tab set here?
pop si
pop dx
jnc tabsta3 ; nc = no
mov dl,'T' ; yes, display a 'T'
tabsta3:push ax
mov al,dl
stosb
pop ax
inc cl
cmp cl,byte ptr low_rgt ; done yet?
jb tabsta1 ; b = not yet
pop dx
ret
tabstat endp
filler proc near ; use space
mov cx,20
mov al,' '
cld
rep stosb
ret
filler endp
VTSTAT endp ; end of Terminal set & status code
scrini proc near ; init screen stuff
mov ega_mode,0 ; assume no EGA
mov ax,1200H ; EGA: Bios alternate select
mov bl,10H ; Ask for EGA info
mov bh,0ffH ; Bad info, for testing
mov cl,0fH ; Reserved switch settings
int screen ; EGA, are you there?
cmp cl,0cH ; Test reserved switch settings
jge scrin1 ; ge = no EGA in use
push es
mov ax,40h ; check Bios 40:87h for ega being
mov es,ax ; the active display adapter
test byte ptr es:[87h],8 ; is ega active?
pop es
jnz scrin1 ; nz = no
mov ega_mode,1 ; yes, set flag to say so
mov crt_norm,3 ; assume color monitor is attached
or bh,bh ; is color mode in effect?
jz scrin1 ; z = yes
mov crt_norm,7 ; else use mode 7 for mono
scrin1: call scrseg ; update screen segment tv_seg(s/o)
call scrmod ; get screen mode, low_rgt
call getpos ; get cursor position and type
jcxz scrin2 ; z = nothing there, skip this
mov lincur,cx ; save cursor type (scan line #'s)
scrin2: mov bx,vtemu.att_ptr
mov ah,[bx]
and ah,att_intensity
mov userbold,ah ; remember old bold
mov ax,word ptr crt_cols ; present screen text size
cmp ax,savflg ; vs size of saved screen
je scrin3 ; e = same, do not re-initialize
;
call bufadj ; re-initialize screen buffers
mov cursor,0 ; cursor to upper left corner
cmp flags.vtflg,0 ; terminal type of None?
ja scrin3 ; a = no, emulating
mov dh,byte ptr low_rgt+1
inc dh ; bottom
xor dl,dl ; left corner
mov cursor,dx ; non-emulating cursor
; Common finish code
scrin3: mov ah,savattr ; saved emulator attributes
mov scbattr,ah ; restore active value
mov dx,cursor ; use old cursor, if any
call setpos ; set cursor position
call restscr ; restore screen, if any saved
cmp vtinited,inited ; inited emulator yet?
je scrin11 ; e = yes
scrin10:call vtinit ; init it now
jmp short scrin13
scrin11:call ansrei ; reinit the emulator
cmp flags.vtflg,tttek ; Tek mode?
je scrin12 ; e = yes
test tekflg,1 ; Tek mode?
jz scrin13 ; z = no
scrin12:call tekini
scrin13:mov al,flags.vtflg ; current terminal type
mov trmtyp,al ; place to remember it til next time
mov vtclear,0 ; clear the clear-screen flag
ret
scrini endp
; Routine to initialize VT102/52/Heath-19 terminal emulator.
vtinit proc near
mov holdscr,0 ; clear holdscreen
call kbhold ; tell DEC LK250 the state, in msuibm
or vtinited,inited
mov bx,argadr ; address of argument block
mov dl,[bx].flgs
and dl,lclecho ; local echo flag
and yflags,not lclecho
or yflags,dl
mov dl,[bx].baudb ; baud rate code in dl
mov dh,[bx].parity ; parity code in bits
mov cl,4 ; 0-3 of dh
shl dh,cl
or dh,07H ; just say 7 data bits
test flags.remflg,d8bit ; eight bit display?
jz vtini1 ; z = no
inc dh ; set low four bits to value 8
vtini1: cmp flags.vtflg,0 ; doing emulation?
je vtini3 ; e = no
test tekflg,1 ; Tek sub-mode active?
jnz vtini2 ; nz = yes, do it's reinit
call ansini ; call startup routine in mszibm
cmp flags.vtflg,tttek ; full Tek mode?
je vtini2 ; e = yes
vtinix: clc
ret
vtini2: call tekrint ; reinitialize Tek emulator
clc
ret
vtini3: call cmblnk ; clear the screen
clc
ret
vtinit endp
argini proc near ; read passed arguments
mov bx,argadr ; base of argument block
mov al,[bx].flgs ; get flags
and al,capt+emheath+trnctl+lclecho+modoff
mov yflags,al ; mask for allowable and save
mov al,[bx].prt
mov portno,al ; update port number
mov ax,[bx].captr
mov captrtn,ax ; buffer capture routine
mov parmsk,0ffh ; parity mask, assume parity = None
cmp [bx].parity,parnon ; is parity None?
je argini1 ; e = yes, keep all 8 bits
mov parmsk,07fh ; else keep lower 7 bits
argini1:ret
argini endp
term proc near ; terminal mode entry point
mov bx,portval ; port data structure address
mov bx,[bx].flowc ; get flow control chars (bl=xoff)
mov flowon,bh
mov flowoff,bl ; save for later
mov oldsp,sp ; remember stack for i/o failure,
mov argadr,ax ; save argument ptr
call argini ; init options from arg address
call scrmod ; get screen mode now
mov ah,crt_cols ; screen width
cmp ah,dos_cols ; has it changed?
je term1 ; e = no
mov dos_cols,ah ; remember for exiting Connect mode
mov vtinited,0 ; need to reset emulator too
and vtemu.vtflgop,not deccol; set emulator to 80 column mode
and vtemu.vtflgst,not deccol
cmp crt_cols,80 ; narrow width now?
jbe term1 ; be = yes
or vtemu.vtflgop,deccol ; set emulator to 132 column mode
or vtemu.vtflgst,deccol
term1: mov ax,100h ; assume 80 column mode, no-renter
test vtemu.vtflgop,deccol ; supposed to be in 80 col?
jz term2 ; z = yes
inc al ; say want 132 cols
term2: call chgdsp ; set to 80/132 columns
call scrmod ; update emulator screen dimensions
cmp crt_cols,80 ; 80 cols now?
ja term2a ; a = no
and vtemu.vtflgop,not deccol; tell emulator 80 column mode
and vtemu.vtflgst,not deccol
jmp short term3
term2a: or vtemu.vtflgop,deccol ; tell emulator 132 column mode
or vtemu.vtflgst,deccol
term3: call scrini ; init screen stuff
or kbcodes,80h ; set need-to-init flg for kbd xtlator
mov fairprn,0 ; set printer buffer flush counter
lp: call prtchr ; char at port?
jnc short lpinp ; nc = yes, go handle
push bx
mov bx,portval ; port structure address
cmp [bx].portrdy,0 ; is port ready for business?
pop bx
jne lpkbd ; ne = ready
jmp endcon ; end the communications now
lpkbd: mov fairness,0 ; say kbd was examined
call dvpause ; tell DESQview we are not busy
inc fairprn ; inc printer dump counter
cmp fairprn,1000 ; been here enough times now?
jb lpkbd1 ; b = no
call pntflsh ; flush printer buffer
jnc lpkbd0 ; nc = success
call pntdead ; call bad printer notifier
lpkbd0: mov fairprn,0 ; reset for next time
lpkbd1: call keybd ; call keyboard translator in msu
jnc lp ; nc = no char or have processed it
jmp short quit ; carry set = quit connect mode
lpinp: and al,parmsk ; apply 8/7 bit parity mask
call outtty ; print on terminal
inc fairness ; say read port but not kbd, again
cmp fairness,100 ; this many port reads before kbd?
jb lp ; b = no, read port again
jmp short lpkbd ; yes, let user have a chance too
quit: mov ah,scbattr ; current emulator attributes
mov savattr,ah ; save them here
call pntflsh ; flush printer buffer
call tekend ; cleanup Tektronix mode [bjh]
call getpos ; get cursor position into dx
mov cursor,dx ; save position
mov al,1
call csrtype ; turn on underline cursor
cmp flags.vtflg,0 ; terminal type of none?
je quit1 ; e = yes
cmp flags.modflg,2 ; is modeline owned by remote host?
je quit1 ; e = yes
call clrmod ; clear it before storing screen
quit1: call savescr ; save screen
mov ah,dosattr ; attributes at init time
mov scbattr,ah ; background = original state
call clrmod ; clear mode line with old attributes
mov ax,100h ; assume using 80 col screen
cmp dos_cols,80 ; startup screen width
jbe quit1a ; be = assume 80 columns
inc al ; say do 132 columns
quit1a: call chgdsp ; reset display width to startup
call scrmod ; update size info
; for ega in non-standard # lines
cmp ega_mode,0 ; ega board active?
je quit2 ; e = no
cmp byte ptr low_rgt+1,23 ; is screen standard length?
je quit2 ; e = yes, so regular cursor set is ok
push es ; turn off ega cursor emulation
mov ax,40h ; byte 40:87H is ega Info byte
mov es,ax
push es:[87h] ; save info byte around call
or byte ptr es:[87h],1 ; set emulation off (low bit = 1)
mov cx,lincur ; cursor shape to set
mov ah,1 ; set the shape
int screen ; back to starting value
pop es:[87h] ; recover original Info byte
pop es ; and our work reg
jmp short quit3 ; skip regular mode cursor setting
quit2: ; for regular sized screen
mov cx,lincur ; cursor type at startup
mov ah,1
int screen ; restore cursor type
quit3: mov dh,byte ptr low_rgt+1 ; bottom line
inc dh ; status line position
xor dl,dl ; left most column
call setpos ; set cursor position
mov al,yflags
and al,not lclecho ; don't copy host's echo flag
mov bx,argadr
mov ah,[bx].flgs ; get user's flag settings
and ah,lclecho ; clear all but local echo bit
or [bx].flgs,al ; update flags in arg block
call dvpause ; tell DESQview we are not busy
ret
term endp
; put the character in al to the screen
outtty proc near
test flags.remflg,d8bit ; keep 8 bits for displays?
jnz outtt1 ; nz = yes, 8 bits if possible
and al,7fh ; remove high bit
outtt1: cmp flags.vtflg,0 ; emulating a terminal?
je outnp10 ; e = no
cmp vtroll,0 ; auto roll back allowed?
je outem1 ; e = no, leave screen as is
cmp tekflg,0 ; Tek mode active?
jne outem1 ; ne = yes, skip screen rolling
cmp flags.vtflg,tttek ; doing Tektronix emulation?
je outem2 ; e = yes, use Tek emulator
push ax ; (BDT) save this for a tad
mov ax,linec ; (BDT) are we at the buffer end?
cmp ax,lcnt ; (BDT) ...
pop ax ; (BDT) restore the register
je outem1 ; (BDT) e = yes
push ax ; (BDT) save AX again
call endwnd ; (BDT) restore screen [dlk]
pop ax ; (BDT) restore the register
outem1: cmp flags.vtflg,tttek ; doing Tektronix emulation?
je outem2 ; e = yes, use Tek emulator
cmp tekflg,0 ; Tek submode active for input?
jne outem2 ; ne = yes, use Tek emulator
jmp anstty ; call terminal emulator routine & ret
outem2: call tekemu ; use Tek emulator and return
ret
; use DOS for screen output
outnp10:test flags.remflg,d8bit ; keep 8 bits for displays?
jnz outnp9 ; nz = yes, 8 bits if possible
and al,7fh ; remove high bit
outnp9: cmp rxtable+256,0 ; translation turned off?
je outnp7 ; e = yes, no translation
push bx
mov bx,offset rxtable ; address of translate table
xlatb ; new char is in al
pop bx
outnp7: test anspflg,prtscr ; should we be printing?
jz outnp8 ; no, keep going
call pntchr ; queue char for printer
jnc outnp8 ; nc = successful print
push ax
call vtbell ; else make a noise and
call trnprs ; turn off printing
pop ax
outnp8: test yflags,capt ; capturing output?
jz outnp6 ; no, forget this part
push ax ; save char
call captrtn ; give it captured character
pop ax ; restore character and keep going
outnp6: test yflags,trnctl ; debug? if so use Bios tty mode
jz outnp4 ; z = no
mov ah,conout ; DOS screen write
cmp al,7fh ; Ascii Del char or greater?
jb outnp1 ; b = no
je outnp0 ; e = Del char
push ax ; save the char
mov dl,7eh ; output a tilde for 8th bit
int dos
pop ax ; restore char
and al,7fh ; strip high bit
outnp0: cmp al,7fh ; is char now a DEL?
jne outnp1 ; ne = no
and al,3fH ; strip next highest bit (Del --> '?')
jmp outnp2 ; send, preceded by caret
outnp1: cmp al,' ' ; control char?
jae outnp3 ; ae = no
add al,'A'-1 ; make visible
outnp2: push ax ; save char
mov dl,5eh ; caret
int dos ; display it
pop ax ; recover the non-printable char
outnp3: push ax
mov dl,al
int dos
pop ax
ret
outnp4: cmp al,bell ; bell (Control G)?
jne outnp5 ; ne = no
jmp vtbell ; use short beep, avoid char loss
outnp5: mov dl,al ; write without intervention
mov ah,conout
int dos ; else let dos display char
ret
outtty endp
;[IU2] Here to output an unsigned 8-bit number (in al) to the port
; Used by terminal emulator escape sequence output.
prtnout proc near
mov bl,10 ; Output in base 10
jmp prtno2 ; Ensure at least a zero
prtno1: or al,al
jnz prtno2 ; nz = yes, do more digits
ret ; no, return from recursive call
prtno2: xor ah,ah ; clear previous remainder
div bl ; divide off a digit
push ax ; push remainder (in ah) on stack
call prtno1 ; recurse
pop ax ; pop off a digit
add ah,'0' ; make it ASCII
mov al,ah ; send to port, in ah
call outprt
jc prtno3 ; failure, end connection
ret
prtno3: jmp endcon
prtnout endp
; send the character in al out to the serial port; handle echoing.
; Can send an 8 bit char while displaying only 7 bits locally.
outprt proc near
mov ah,1 ; say local echo is permitted
jmp short outprt0
prtbout:xor ah,ah ; no local echo
outprt0:test al,80h ; high bit set?
jz outpr2 ; z = no
cmp al,9fh ; above C1 area?
ja outpr2 ; a = yes
test vtemu.vtflgop,vscntl ; doing 8-bit controls?
jz outprt5 ; z = no, send 7-bit control seq
cmp parmsk,7fh ; using parity?
jne outpr2 ; ne = no
outprt5:cmp al,0a0h ; in GR?
ja outpr1 ; a = yes, else C1
push ax ; save char
mov al,Escape ; C1 as ESCAPE <char-40h>
call outpr2 ; send ESCAPE
pop ax ; recover char
sub al,40h ; strip high bit, relocate code
jmp short outpr2 ; send the char
outpr1: push ax ; save char
mov al,Escape ; send as ESC N char & 7fh
call outpr2 ; ESC N is Single Shift 2
mov al,'N'
call outpr2
pop ax ; recover char
and al,not 80h ; strip high bit
outpr2: or ah,ah ; local echo permitted?
jz outpr3 ; z = no
test yflags,lclecho ; echoing?
jz outpr3 ; z = no, forget it
push ax ; save char
call outtty ; display it
pop ax ; restore
outpr3: mov ah,al ; this is where outchr expects it
call outchr ; output to the port
jc outpr4 ; c = failure
ret
outpr4: jmp endcon ; failure, end connection
outprt endp
; Jump here to exit Connect mode and execute macros 'TERMINALR' (vtrmac) or
; 'TERMINALS' (vtsmac). Does nothing if macro does not exist.
; Preserves registers except ax. Returns to TELNET caller with 'C' in kbdflg.
vtrmac proc near ; RESET macro
mov vtmacname,offset vtrname ; select macro name
mov vtmaclen,vtrlen ; and its length
call dword ptr vtmacroptr ; FAR pointer, finish in common code
ret
vtrmac endp
vtsmac proc near ; SET macro
mov vtmacname,offset vtsname
mov vtmaclen,vtslen
call dword ptr vtmacroptr ; FAR pointer
ret
vtsmac endp
; Invoked by keyboard translator when an unknown keyboard verb is used as
; a string definition, such as {\ktest}. Enter with vtmacname pointing to
; uppercased verb name, asciiz, and vtmaclen set to its length.
extmacro proc near
call dword ptr vtmacroptr ; FAR pointer
ret
extmacro endp
; Same as TERMINALR/S except invokes macro PRODUCT with variables \%1..\%9
; defined as the ascii renditions of the control sequence numeric paramters
; param[0]..param[8], and sets script ARGC item to one greater than this.
product proc near
call dword ptr productptr ; FAR pointer
ret
product endp
; support for vtmacro and fproduct
fdec2di proc far
call dec2di
ret
fdec2di endp
code ends
code1 segment
assume cs:code1
fproduct proc far
push si
push di
push es
mov ax,ds
mov es,ax
mov di,offset rdbuf+2 ; macro def buffer starts here
mov si,offset prodname ; pointer to macro name
mov cx,vtplen ; length of macro name
cld
rep movsb ; copy to rdbuf+2
mov byte ptr [di],0 ; null terminator
mov cx,nparam ; number of parameters
cmp cx,9 ; more than 9?
jle produc1 ; le = no
mov cx,9 ; limit to 9
produc1:jcxz produc3 ; z = none
xor bx,bx ; parameter subscript
produc2:push bx
push cx
mov al,' ' ; and a space separator
stosb
shl bx,1 ; address words
mov ax,param[bx] ; get parameter to use as definition
call fdec2di ; convert numerics to ascii string
pop cx
pop bx
inc bx
loop produc2
produc3:xor al,al ; safety terminator
mov [di],al ; don't count in length
mov ax,di
sub ax,offset rdbuf ; compute length
mov vtmaclen,ax ; pass along to vtmacro
mov vtmacname,offset rdbuf+2 ; say this is our macro text ptr
pop si
pop di
pop es
jmp short vtmacro
fproduct endp
;
; Reference Macro structure for db number of entries (mac names)
; is file table mcctab |-> dw length of macroname
; mssset.asm each entry |-> db 'macroname'
; where these |-> dw segment:0 of definition string
; are stored. (offset part is always 0)
; Definition string in db length of <string with null>
; buffer macbuf db 'string with trailing null'
;
vtmacro proc far ; common code for macros vtsmac,vtrmac
push bx ; and Product
push cx
push si
push di
push es
mov ax,ds
mov es,ax
mov di,offset rdbuf+2 ; macro def buffer starts here
mov si,vtmacname ; pointer to macro name
mov cx,vtmaclen ; length of macro name<sp/null>text
mov [di-2],cx ; counted string field
cld
rep movsb ; copy to rdbuf
mov byte ptr [di],0 ; null terminator
mov si,offset rdbuf+2 ; look for name-text separator
mov cx,vtmaclen
vtmac1: lodsb
cmp al,' ' ; space separator?
je vtmac1a ; e = yes, stop here
or al,al ; null terminator?
jz vtmac1a ; e = yes, stop here
loop vtmac1
inc si ; to do null length correctly
vtmac1a:sub si,offset rdbuf+2+1 ; compute length of macro name
mov cx,si
mov vtmaclen,cx ; save a macro name length
; check for existence of macro
mov bx,offset mcctab ; table of macro names
mov cl,[bx] ; number of names in table
xor ch,ch
jcxz vtmacx ; z = empty table, do nothing
inc bx ; point to length of first name
vtmac2: mov ax,[bx] ; length of this name
cmp ax,vtmaclen ; length same as desired keyword?
jne vtmac3 ; ne = no, search again
mov si,bx
add si,2 ; point at first char of name
push cx ; save name counter
push di ; save reg
mov cx,vtmaclen ; length of name
mov di,vtmacname ; point at desired macro name
push es ; save reg
push ds
pop es ; make es use data segment
cld
repe cmpsb ; match strings
pop es ; need current si below
pop cx
pop di ; recover saved regs
je vtmac4 ; e = matched
vtmac3: add bx,ax ; step to next name, add name length
add bx,4 ; + count and def word ptr
loop vtmac2 ; try next name
vtmacx: pop es
pop di
pop si ; no macro, return to Connect mode
pop cx
pop bx
ret
vtmac4: cmp taklev,maxtak ; room in Take level?
jge vtmacx ; ge = no, exit with no action
inc taklev ; increment take level
add takadr,size takinfo ; make a new Take entry/macro
mov bx,takadr ; point to current macro structure
mov ax,ds ; segment of rdbuf
mov [bx].takbuf,ax ; segment of definition string struc
mov cx,word ptr rdbuf ; length of count + string
mov [bx].takcnt,cx ; number of chars in definition
mov [bx].takargc,0 ; our argument count
mov [bx].takptr,offset rdbuf+2 ; where to read next command char
mov [bx].taktyp,0ffh ; flag as a macro
pop es
pop di
pop si
pop cx
pop bx
jmp dword ptr endconptr ; exit Connect mode
vtmacro endp
code1 ends
code segment
assume cs:code
; Error recovery routine used when outchr reports unable to send character
; or when vtmacro requests exiting Connect mode.
; Exit Connect mode cleanly, despite layers of intermediate calls.
endcon proc near
mov kbdflg,'C' ; report 'C' to TERM's caller
mov sp,oldsp ; recover startup stack pointer
; TERM caller's return address is now
; on the top of stack. A longjmp.
jmp quit ; exit Connect mode cleanly
endcon endp
;;; Action routines (verbs) for keyboard translator KEYBD in msuibm.
; These are invoked by a jump instruction. Return carry clear for normal
; processing, return carry set for invoking Quit (kbdflg has transfer char).
uparrw: mov al,'A' ; cursor keys
jmp short comarr
dnarrw: mov al,'B'
jmp short comarr
rtarr: mov al,'C'
test vtemu.vtflgop,vswdir ; writing left to right?
jz comarr ; z = yes
mov al,'D' ; reverse sense of keys
jmp short comarr
lfarr: mov al,'D'
test vtemu.vtflgop,vswdir ; writing left to right?
jz comarr ; z = yes
mov al,'C' ; reverse sense of keys
comarr: push ax ; save final char
mov ttyact,0 ; network, group chars for packet
test vtemu.vtflgop,decanm ; ANSI mode?
jz comar2 ; z = no
mov al,CSI ; CSI character
test vtemu.vtflgop,decckm ; cursor key mode reset?
jz comar1 ; z = yes
mov al,SS3 ; SS3 character
comar1: call outprt ; send in 7 or 8 bit form, with echo
jmp short comar3
comar2: mov al,escape ; do Heath/VT52 mode "ESC char"
call outprt
comar3: pop ax ; recover final char
mov ttyact,1 ; network, restore tty active flag
call outprt
ret
pf1: mov al,'P' ; keypad function keys PF1-4
jmp short compf
pf2: mov al,'Q'
jmp short compf
pf3: mov al,'R'
jmp short compf
pf4: mov al,'S'
compf: push ax ; save final char
mov ttyact,0 ; network, group chars for packet
test vtemu.vtflgop,decanm ; ansi mode?
jz short compf1 ; z = no
mov al,SS3
call outprt ; send 7 or 8 bit version
jmp short compf2
compf1: mov al,escape ; output ESC
call outprt
compf2: pop ax ; get the saved char
mov ttyact,1 ; network, restore tty active flag
call outprt
ret
kp0: mov al,'p' ; keypad numeric keys
jmp short comkp
kp1: mov al,'q'
jmp short comkp
kp2: mov al,'r'
jmp short comkp
kp3: mov al,'s'
jmp short comkp
kp4: mov al,'t'
jmp short comkp
kp5: mov al,'u'
jmp short comkp
kp6: mov al,'v'
jmp short comkp
kp7: mov al,'w'
jmp short comkp
kp8: mov al,'x'
jmp short comkp
kp9: mov al,'y'
jmp short comkp
kpminus:mov al,'m'
jmp short comkp
kpcoma: mov al,'l'
jmp short comkp
kpenter:mov al,'M'
jmp short comkp
kpdot: mov al,'n'
comkp: test vtemu.vtflgop,deckpam ; keypad application mode active?
jnz comkp1 ; nz = yes, use escape sequences
sub al,40h ; deduct offset to numeric symbols
push ax ; save final char
jmp short comkp3 ; and send that single char
comkp1: push ax
mov ttyact,0 ; network, group chars for packet
test vtemu.vtflgop,decanm ; ANSI mode?
jz comkp2 ; z = no
mov al,SS3 ; SS3 character
call outprt ; send 7 or 8 bit version
jmp short comkp3
comkp2: mov al,escape ; output "ESC ?"
call outprt
mov al,'?'
call outprt
comkp3: pop ax ; recover final char
mov ttyact,1 ; network, restore tty active flag
call outprt ; send it
ret
klogon proc near ; resume logging (if any)
test flags.capflg,logses ; session logging enabled?
jz klogn ; z = no, forget it
push bx
mov bx,argadr
or [bx].flgs,capt ; turn on capture flag
pop bx
or yflags,capt ; set local msy flag as well
klogn: clc
ret
klogon endp
klogof proc near ; suspend logging (if any)
push bx
mov bx,argadr
and [bx].flgs,not capt ; stop capturing
pop bx
and yflags,not capt ; reset local msy flag as well
clc
ret
klogof endp
snull proc near ; send a null byte
xor al,al ; the null
jmp prtbout ; send without logging and local echo
snull endp
khold: xor holdscr,1 ; toggle Hold screen byte for msx
call kbhold ; tell DEC LK250 the hold kbd state
clc ; kbhold is in file msuibm.asm
ret
; DEC LK201 keyboard keys and "User Definable Keys" in VT3xx mode
decfind:mov al,1 ; Find
jmp udkout
decinsert:mov al,2 ; Insert
jmp udkout
decremove:mov al,3 ; Remove
jmp udkout
decselect:mov al,4 ; Select
jmp udkout
decprev:mov al,5 ; Previous screen
jmp udkout
decnext:mov al,6 ; Next screen
jmp udkout
decf6: mov al,17 ; key ident for DEC F6
jmp udkout ; process it
decf7: mov al,18 ; key ident for DEC F7
jmp udkout ; process it
decf8: mov al,19 ; key ident for DEC F8
jmp udkout ; process it
decf9: mov al,20 ; key ident for DEC F9
jmp udkout ; process it
decf10: mov al,21 ; key ident for DEC F10
jmp udkout ; process it
decf11: mov al,23 ; key ident for DEC F11
jmp udkout ; process it
decf12: mov al,24 ; key ident for DEC F12
jmp udkout ; process it
decf13: mov al,25 ; key ident for DEC F13
jmp udkout ; process it
decf14: mov al,26 ; key ident for DEC F14
jmp udkout ; process it
dechelp:mov al,28 ; key ident for DEC HELP
jmp udkout ; process it
decdo: mov al,29 ; key ident for DEC DO
jmp udkout ; process it
decf17: mov al,31 ; key ident for DEC F17
jmp udkout ; process it
decf18: mov al,32 ; key ident for DEC F18
jmp udkout ; process it
decf19: mov al,33 ; key ident for DEC F19
jmp udkout ; process it
decf20: mov al,34 ; key ident for DEC F20
jmp udkout ; process it
; common worker to output contents of User Definable Key definition strings
; Enter with al = key ident (17 - 34)
udkout proc near
push ax
push bx
push cx
push es
test flags.vtflg,ttvt320+ttvt220 ; VT320/VT220?
jnz udkout3 ; nz = yes, else use VT100/VT52 default
test flags.vtflg,tttek ; Tek?
jnz udkout3 ; nz = yes, try this
cmp al,23 ; F11 sends ESC
jne udkou1a ; ne = not F11
mov al,escape
call outprt
jmp udkoutx
udkou1a:cmp al,24 ; F12 sends BS
jne udkou1b ; ne = not F12
mov al,BS
call outprt
jmp udkoutx
udkou1b:cmp al,25 ; F13 sends LF
jne udkou1c ; ne = not F13, ignore
mov al,LF
call outprt
udkou1c:jmp udkoutx
udkout3:mov bl,al ; VT3XX key ident, UDK style (17-34)
cmp al,6 ; is this the CSI 1-6 set?
jbe udkout4 ; be = yes, do separately
sub bl,17 ; minus starting offset of 17
xor bh,bh
cmp bl,17 ; out of range?
ja udkoutx ; a = yes, ignore
shl bx,1 ; index words
mov bx,udkseg[bx] ; segment of definition
or bx,bx ; anything there?
jz udkout4 ; z = no, use DEC defaults below
mov es,bx ; definition segment
xor bx,bx ; and offset
mov cl,es:[bx] ; get string length byte
xor ch,ch ; use cx as a counter
jcxz udkout4 ; z = empty, use defaults
udkou3a:inc bx ; es:bx is now the string text
mov al,es:[bx] ; get a char
push bx
push cx
push es
call outprt ; output
pop es
pop cx
pop bx
loop udkou3a
jmp short udkoutx ; done
udkout4:push ax ; VT320, use default definitions
mov al,CSI ; char to send
call outprt ; send lead-in char in 7/8-bit form
pop ax
call prtnout ; key ident (17-34) as ascii digits
mov al,7eh ; tilde terminator
call outprt
udkoutx:pop es
pop cx
pop bx
pop ax
clc
ret
udkout endp
; Set (define) the DEC "User Definable Keys". Inserts text definitions for
; keyboard verbs \KdecF6 ...\KdecF14, \KdecHELP, \KdecDO, \KdecF17...\KdecF20.
; Enter with the DCS definition string as key-number/hex-chars. UDK key number
; is 17 for \KdecF6, et seq, the definition are pairs of hex digits converted
; here to a single byte per pair. The DCS definition string is pointed at by
; DS:SI, and the byte count is in CX.
; Example: 17/54657374204636 means key \KdecF6 sends string "Test F6"
setudk proc near
push ax
push bx
push cx
push si
push di
push es
cld
lodsb ; get key ident first byte
sub al,'0' ; ascii to binary
mul ten ; times 10
xchg ah,al ; to ah
lodsb ; get key ident second byte
sub al,'0' ; ascii to binary
add al,ah ; plus high order part
xor ah,ah
mov bx,ax ; key ident, 17 - 34
lodsb ; skip slash separator
sub cx,3 ; three less bytes in the string
jge setudk0 ; ge = had three or more bytes
jmp setudkx ; else error
setudk0:sub bx,17 ; remove key ident bias of 17
cmp bx,17 ; out of range?
ja setudkx ; a = yes, ignore
shl bx,1 ; index words
cmp udkseg[bx],0 ; has a segment been allocated for it?
je setudk1 ; e = no
mov ax,udkseg[bx] ; get segment to es
mov es,ax
mov ah,freemem ; deallocate old memory block, es:0
int dos
mov udkseg[bx],0 ; clear table entry too
setudk1:and cl,not 1 ; force an even number of inputs
jcxz setudkx ; z = no definition, clear entry
push bx ; save index BX
mov bx,cx ; get string length
shr bx,1 ; two hex digits per final byte
add bx,15+1 ; round up plus length byte
shr bx,1 ; convert to paragraphs
shr bx,1
shr bx,1
shr bx,1
mov di,bx ; remember request
mov ah,alloc ; allocate BX paragraphs
int dos
jc setudkx ; c = failure
cmp di,bx ; requested vs allocated
pop bx ; recover bx
je setudk2 ; e = enough
mov ah,freemem ; return the memory, es is ptr
int dos
jmp short setudkx ; exit failure
setudk2:mov es,ax ; segment of allocated memory
mov udkseg[bx],es ; segment:0 of definition string
xor di,di
cld
mov al,cl ; length of string
shr al,1 ; two hex bytes per stored byte
xor ch,ch
stosb ; store length byte
jcxz setudkx ; z = empty string
setukd3:lodsb ; get first hex digit
dec cx ; adjust count remaining
or al,20h ; to lower case
cmp al,'9' ; digit?
jbe setudk4 ; be = yes
sub al,'a'-'9'-10 ; hex letter to column three
setudk4:sub al,'0' ; ascii to binary
shl al,1 ; times 16
shl al,1
shl al,1
shl al,1
mov ah,al ; save in ah
lodsb ; get second hex digit
or al,20h ; to lower case
cmp al,'9' ; digit?
jbe setudk5 ; be = yes
sub al,'a'-'9'-10 ; hex letter to column three
setudk5:sub al,'0' ; ascii to binary
add al,ah ; join both parts
stosb ; store final byte
loop setukd3
setudkx:pop es
pop di
pop si
pop cx
pop bx
pop ax
clc
ret
setudk endp
; Clear all User Definable Keys, deallocate memory for their definitions
udkclear proc near
push ax
push bx
push cx
push es
mov cx,17 ; 17 entries
xor bx,bx
udkcle1:mov ax,udkseg[bx] ; segment of definition
or ax,ax ; segment defined?
jz udkcle2 ; z = no, try next key
mov es,ax
mov udkseg[bx],0 ; clear the entry
mov ah,freemem ; release the memory
int dos
udkcle2:add bx,2 ; word index
loop udkcle1 ; do all
pop es
pop cx
pop bx
pop ax
clc
ret
udkclear endp
; general character out for emulator
chrout: cmp flags.vtflg,0 ; emulating?
je chrou5 ; e = no
call anskbi ; say we had keyboard input
cmp al,cr ; CR?
jne chrou5 ; ne = no, just output it and return
test vtemu.vtflgop,anslnm ; ANSI new-line mode set?
jz chrou5 ; z = no, just send the cr
cmp dupflg,0 ; full duplex?
je chrou4 ; e = yes
cmp al,trans.seol ; End of Line char?
jne chrou5 ; ne = no
chrou4: mov ah,trans.seol ; save eol char
push ax ; save on stack
mov trans.seol,lf ; make LF the eol char
call outprt ; output a carriage-return
mov al,lf ; followed by a line feed
call outprt ; send the LF
pop ax
mov trans.seol,ah ; restore eol char
ret
chrou5: jmp outprt
; these commands invoke Quit
cdos: mov al,'P' ; Push to DOS
jmp short cmdcom
cstatus:mov al,'S' ; Status
jmp short cmdcom
cquit: mov al,'C' ; Exit Connect mode
jmp short cmdcom
cquery: mov al,'?' ; Help
jmp short cmdcom
chang: mov al,'H' ; Hangup, drop DTR & RTS
jmp short cmdcom
cmdcom: mov kbdflg,al ; pass char to msster.asm via kbdflg
stc ; signal that Quit is needed
ret
; Screen dump entry from keyboad xlat
dmpscn proc near ; dump screen to file
cmp flags.vtflg,tttek ; doing Tektronix emulation?
je dmpscn2 ; e = yes, use Tek emulator
test tekflg,1 ; emulation a Tektronix?
jz dmpscn1 ; z = no
dmpscn2:call tekdmp ; near-call Tek screen dump utility
clc
ret
dmpscn1:call savescr ; save screen to buffer
call dumpscr ; do buffer to file
clc ; do not exit Connect mode
ret
dmpscn endp
;[IU2] Routine to toggle VT100/VT52/Heath-19 modes in VT100 emulator.
vtans52 proc near
cmp flags.vtflg,0 ; emulating?
je vtans5 ; e = no
call ans52t ; call MSZ toggle-it routine
clc ; clear c bit so don't exit Connect
vtans5: ret
vtans52 endp
; Toggle Mode Line
trnmod proc near
cmp flags.modflg,1 ; mode line enabled and owned by us?
jne trnm1 ; ne = no, don't touch it
cmp flags.vtflg,tttek ; Tek mode?
je trnm3 ; e = yes
cmp tekflg,0 ; Tek submode?
jne trnm3 ; ne = yes, no mode line changes
test yflags,modoff ; mode line already off?
jnz trnm2 ; nz = yes, go turn on
or yflags,modoff ; say modeline is toggled off
call clrmod ; clear mode line
trnm1: clc ; clear c bit so don't exit Connect
ret
trnm2: cmp flags.vtflg,0 ; emulating a terminal?
jne trnm3 ; ne = yes
push dx ; scroll screen to save bottom line
mov ah,prstr ; for terminal type none
mov dx,offset crlf
int dos
pop dx
trnm3: call modlin ; turn on modeline
and yflags,not modoff ; say modeline is not toggled off
clc
ret
trnmod endp
modlin proc near ; turn on mode line
push es
mov ax,ds
mov es,ax
mov si,offset modmaster ; master template
mov di,offset modbuf ; working copy
cld
modl20: lodsb
stosb
cmp al,'$' ; at end?
jne modl20 ; ne = no
mov al,trans.escchr ; Connect mode escape character
mov modbuf.m_echr,' ' ; first char is initial space
mov modbuf.m_hlp,' ' ; goes here too
cmp al,32 ; printable?
jnb modl1 ; yes, keep going
add al,40h ; made printable
mov modbuf.m_echr,5eh ; caret, note control char
mov modbuf.m_hlp,5eh
modl1: mov modbuf.m_echr+1,al ; fill in character
mov modbuf.m_hlp+1,al
mov bx,argadr ; get argument block
mov al,[bx].baudb ; get baud bits
mov si,offset unkbaud ; assume unknown baud
mov cx,size m_baud ; length of baud space
cmp al,baudnsiz ; beyond end of table?
jnb modl2 ; nb = yes, use default
mul cl
xor ah,ah
add ax,offset baudn
mov si,ax
modl2: mov di,offset modbuf.m_baud
cld
rep movsb ; copy in baud rate
mov al,[bx].parity ; get parity code
shl al,1 ; each is 4 bytes long
shl al,1
xor ah,ah
add ax,offset parnams ; names of parity settings
mov si,ax
mov cx,4 ; each is 4 long
mov di,offset modbuf.m_par
rep movsb
mov si,offset remmsg ; assume remote echoing
test yflags,lclecho ; local echo on?
jz modl3 ; z = no
mov si,offset lclmsg ; say echo is local
modl3: mov cx,3 ; size of on/off
mov di,offset modbuf.m_echo
rep movsb
mov al,portno ; communications port
cmp al,' ' ; binary (non-printable)?
jae modl4 ; ae = no, ascii
add al,'0' ; convert to ascii
modl4: mov modbuf.m_prt,al ; fill in port number
mov al,portno
cmp repflg,0 ; REPLAY?
je modl5 ; e = no
mov si,offset repmsg ; say "REPLAY"
mov cx,repmsgl ; its length
mov di,offset modbuf.m_prt
mov al,' ' ; start with a space
stosb
mov dx,12 ; space to be filled
sub dx,cx ; amount we will use here
rep movsb ; copy string
mov cx,dx
rep stosb ; flesh out with spaces
jmp short modl10
modl5: cmp al,'4' ; in networks material?
jbe modl10 ; be = no
mov bx,offset comptab ; table of comms ports
mov cl,[bx] ; number of entries
xor ch,ch
inc bx
modl6: mov dx,[bx] ; length of this entry
mov si,bx
add si,2 ; points to entry text string
add si,dx ; point to qualifier
cmp [si],al ; our port?
je modl7 ; e = yes
add bx,[bx] ; add text length
add bx,4 ; plus count and qualifier
loop modl6 ; next entry
jmp short modl10 ; no match, curious
modl7: mov si,bx ; point at entry
add si,2 ; point at string
mov cx,[bx] ; length of string
mov di,offset modbuf.m_prt
mov al,' ' ; start with a space
stosb
mov dx,12 ; space to be filled
sub dx,cx ; amount we will use here
rep movsb ; copy string
mov cx,dx
rep stosb ; flesh out with spaces
modl10:
mov cx,8 ; blank out terminal id field
mov si,offset mtty ; assume no terminal emulation
mov di,offset modbuf.m_term ; destination
rep movsb ; copy it in
mov word ptr modbuf.m_prn,' '; assume not printing the screen
mov modbuf.m_prn+2,' '
test anspflg,prtscr+2 ; print the screen? (msz uses 1 & 2)
jz modl11 ; z = no
mov word ptr modbuf.m_prn,'RP' ; yes. display PRN at end of line
mov modbuf.m_prn+2,'N'
modl11: call getpos ; get cursor position
mov cursor,dx ; save cursor position
mov dx,offset modbuf ; mode line image ptr for putmod
call putmod ; display mode line
cmp flags.vtflg,0 ; emulating?
je modl12 ; e = no
and yflags,not modoff ; update local flags (mode line on)
call ansdsl ; get extras from emulator
modl12: mov dx,cursor
pop es
jmp setpos ; reposition cursor
modlin endp
trnprs: push ax ; toggle ^ PrtSc screen to printer
test anspflg,prtscr ; are we currently printing?
jnz trnpr2 ; nz = yes, its on and going off
push bx
mov bx,prnhand ; file handle for system printer
mov ah,ioctl
mov al,7 ; get output status of printer
int dos
pop bx
jc trnpr1 ; c = printer not ready
cmp al,0ffh ; Ready status?
je trnpr2 ; e = Ready
trnpr1: call vtbell ; Not Ready, complain
jmp trnpr3 ; and ignore request
trnpr2: xor anspflg,prtscr ; flip the flag
test yflags,modoff ; mode line off?
jnz trnpr3 ; nz = yes
call modlin ; else rewrite mode line
trnpr3: pop ax
clc ; return carry clear (don't quit)
ret
pntdead proc near ; display printer is inoperative msg
push ax
test yflags,modoff ; is mode line off?
jnz pntdea1 ; nz = off, skip msg
push bx
mov dx,offset pntmsg ; say printer not ready
call putmod ; write on mode line
pop bx
pntdea1:pop ax
stc ; say printer not ready
ret
pntdead endp
;;;;; General screen management routines for IBM PC
; computes screen location to ax, given row and col in [dh,dl], resp.
scrloc proc near
mov al,dh ; get row
mul crt_cols ; multiply by number of columns
add al,dl ; plus current column number
adc ah,0 ; ripple carry
shl ax,1 ; double for attributes
ret
scrloc endp
; Routine to set cursor type. Pass cursor type in al: 0 = No cursor,
; 1 = Underline cursor, 2 = Block cursor. All cursors blink due to hardware.
; Routine frags any ac that video ints frag.
; For EGA boards running in non-25 line mode the cursor emulation is turned
; off during cursor shape changing and restored afterward. It's another
; ega Feature. [jrd]
; Sense crt_mode 18h as Tseng Labs UltraPAK mono board in 132 column mode.
csrtype proc near
push cx ; save the reg
mov cx,0F00H ; assume no cursor
or al,al ; no cursor?
jz csrty2 ; z = yes, no cursor
cmp crt_mode,7 ; B&W card?
je csrty3 ; e = yes, different sizes
cmp crt_mode,18h ; Tseng UltraPAK mono board?
je csrty3 ; e = yes, use mono cursor
mov cx,0607H ; No, use CGA underline cursor
cmp al,2 ; Block?
jne csrty2 ; ne = no, set it now
csrty1: xor ch,ch ; make cursor a block
csrty2: cmp ega_mode,0 ; ega board active?
je csrty4 ; e = no
cmp byte ptr low_rgt+1,23 ; standard screen length?
je csrty4 ; e = yes, use regular cursor setting
push es ; EGA. turn off cursor emulation
mov ax,40h ; 40:87h is ega Info byte
mov es,ax
push es:[87h] ; save Info byte around call
or byte ptr es:[87h],1 ; set emulation off (low bit = 1)
mov ah,1 ; video function for set cursor type
int screen
pop es:[87h] ; restore Info byte
pop es ; and our work register
pop cx
ret
csrty4: mov ah,1 ; video function for set cursor type
int screen ; regular cursor shape setting
pop cx
ret
csrty3: mov cx,0B0CH ; assume B&W underline cursor
cmp al,2 ; Block?
jne csrty2 ; ne = no, set it now
jmp short csrty1 ; make it a block
csrtype endp
; Get CRT mode - returns mode in variable crt_mode,
; updates crt_cols and low_rgt.
; For EGA active it looks in Bios work memory 40:84H for number of rows
scrmod proc near
push ax
push dx
mov ah,15 ; get current video state
int screen
and al,not 80h ; strip "preserve regen" bit 80h
mov crt_mode,al ; store CRT mode value
mov crt_cols,ah ; store # of cols
mov dl,ah ; # of cols again
mov dh,crt_lins ; and # of rows (constant from msster)
cmp ega_mode,0 ; ega active?
je scrmod4 ; e = no
push es ; yes, permit different lengths
mov ax,40h ; refer to 40:84h for # ega rows
mov es,ax
mov ah,es:[84h] ; get number of rows - 1 (typ 24)
cmp ah,20 ; less than 20 rows?
jb scrmod3 ; b = yes, ignore this length
cmp ah,80 ; more than 80 rows?
ja scrmod3 ; a = yes, ignore this length
mov dh,ah ; use this length
mov crt_lins,dh ; update our working constant
scrmod3:pop es
scrmod4:dec dl ; max text column, count from zero
dec dh ; max text row, count from zero
mov low_rgt,dx ; save away window address
pop dx
pop ax
ret
scrmod endp
; Test for DESQview in operation, set tv_mode bit 10h to non-zero if so.
dvtest proc near
push di
push es
mov ax,tv_segs ; seg of video memory
mov es,ax
mov di,tv_sego ; set to video buffer beginning
and tv_mode,not 10h ; assume no DV
mov cx,'DE' ; DV signature
mov dx,'SQ'
mov ax,2B01h ; DOS set date (with illegal value)
int dos
cmp al,0ffh ; DOS should say invalid if no DV
je dvtest1 ; e = yes, invalid so no DV
or tv_mode,10h ; say using DV
dvtest1:pop es
pop di
ret
dvtest endp
; Execute DESQview function call provided in BX.
dvcall proc near
push ax
mov ax,101ah ; switch to DV stack
int 15h
mov ax,bx ; function to do
int 15h
mov ax,1025h ; switch from DV stack
int 15h
pop ax
ret
dvcall endp
; Call this to release the cpu during idle times
dvpause proc near
test tv_mode,10h ; in DV?
jz dvpaus1 ; z = no
push bx
mov bx,1000h ; say release control
call dvcall ; to DV
pop bx
dvpaus1:ret
dvpause endp
; Get screen segment - returns screen segment in ax, and full address in es:di
scrseg proc near
xor di,di ; start at beginning of screen (0,0)
mov ax,0B800H ; video memory is here on color
cmp crt_mode,7 ; normal color modes?
jb scrse1 ; b = yes
mov ax,0B000H ; assume B&W card
cmp crt_mode,12 ;
jb scrse1
cmp crt_mode,18h ; Tseng UltraPAK mono in 132 col?
je scrse1 ; e = yes, use seg B000H
cmp crt_mode,56h ; Paradise EGA Mono in 132x43 mode?
je scrse1 ; e = yes, use seg B000H
cmp crt_mode,57h ; Paradise EGA Mono in 132x25 mode?
je scrse1 ; e = yes, use seg B000H
mov ax,0B800H ; video memory is here on color
cmp crt_mode,18 ; end of ordinary 640x480 graphics
ja scrse1 ; a = no, assume CGA segment
mov ax,0A000H ; graphics
scrse1: mov es,ax ; tell Topview our hardware address needs
mov tv_segs,es ; save our hardware screen address
mov tv_sego,di ; segment and offset form
or tv_mode,1 ; assume we're running under Topview
mov ah,tvhere ; query Topview for its presence
int screen
mov ax,es ; get its new segment for screen work
cmp ax,tv_segs ; same as hardware?
jne scrse2 ; ne = no, we are being mapped
cmp di,tv_sego ; check this too
jne scrse2 ; ne = no too. Use TV's work buf as screen
and tv_mode,not 1 ; else no Topview or no mapping
scrse2: mov tv_segs,es ; save segment
mov tv_sego,di ; and offset
ret
scrseg endp
; Synchronize a Topview provided virtual screen buffer with the image
; seen by the user. Requires cx = number of words written to screen
; (char & attribute bytes) and es:di = ENDING address of screen write.
; Changes ax and di.
scrsync proc near
cmp tv_mode,0 ; Topview mode active?
je scrsyn1 ; e = no, skip DOS call below
sub di,cx ; backup to start byte (cx = words)
sub di,cx ; after storing words to screen
mov ah,tvsynch ; tell Topview we have changed screen
int screen ; so user sees updated screen
scrsyn1:ret
scrsync endp
; The following two routines are used to turn off the display while we
; are reading or writing the screen in one of the color card modes.
; Turn screen off for (known) color card modes only. All regs preserved.
; Includes code for old procedure scrwait. 16 June 1987 [jrd]
scroff proc near
cmp ega_mode,0 ; Extended Graphics Adapter in use?
jne scrofx ; ne = yes, no waiting
cmp tv_mode,0 ; Topview mode?
jne scrofx ; ne = yes, no waiting
cmp crt_mode,7 ; B&W card?
jnb scrofx ; nb = yes - just return
cmp refresh,0 ; slow refresh?
jne scrofx ; ne = no wait
push ax ; save ax and dx
push dx
mov dx,crt_status ; CGA: Wait for vertical retrace
scrof1: in al,dx
test al,disp_enb ; display enabled?
jnz scrof1 ; yes, keep waiting
scrof2: in al,dx
test al,disp_enb ; now wait for it to go off
jz scrof2 ; so can have whole cycle
mov dx,crtmset ; output to CRT mode set port
mov al,25H ; this shuts down the display
out dx,al
pop dx ; restore regs
pop ax
scrofx: ret
scroff endp
; Turn screen on for (known) color card modes only
; All registers are preserved.
scron proc near
cmp ega_mode,0 ; Extended Graphics Adapter in use?
jne scronx ; ne = yes, no waiting
cmp tv_mode,0 ; Topview mode?
jne scronx ; ne = yes, no waiting
cmp crt_mode,7 ; B&W card?
jnb scronx ; nb = yes - just return
cmp refresh,0 ; slow refresh?
jne scronx ; ne = no wait
push ax ; save ax, dx, and si
push dx
push si
mov al,crt_mode ; convert crt_mode to a word
xor ah,ah
mov si,ax ; get it in a usable register
mov al,msets[si] ; fetch the modeset byte
mov dx,crtmset ; this port
out dx,al ; flash it back on
pop si
pop dx
pop ax
scronx: ret
scron endp
; Screen clearing routine. [IU]
;
; Call: ax/ coordinates of first screen location to be cleared.
; bx/ coordinates of last location to be cleared.
; Coord: ah = row [0-24], al = column [0-79]. Preserves all registers. [jrd]
atsclr: push ax ; save regs
push cx
push dx
mov dx,bx ; compute last screen offset in ax
push ax
call scrmod ; update column length
pop ax ; scrmod zaps ax
push ax
call scrloc ; get screen start address in ax
mov cx,ax ; save it in cx for a minute
pop dx ; compute first screen offset in ax
call scrloc
sub cx,ax ; compute number of locs to clear
add cx,2
sar cx,1 ; make byte count a word count
jle atscl2 ; If nothing to clear, then vamos
push di ; save regs
push es ; save es
push ax ; save displacement
call scrseg ; get address of screen into es:di
pop di ; displacement memory address into di
mov ah,scbattr ; use current screen background attr
mov al,' ' ; use space for fill
call scroff ; turn screen off if color card
atscl1: push cx ; save word count for Topview
cld
rep stosw ; Blit... (excuse PDP-10ese please)
pop cx ; recover word count
call scrsync ; synch Topview
call scron ; Turn screen back on if color card
pop es ; Restore segment register
pop di ; And destination index
atscl2: pop dx ; restore regs
pop cx
pop ax
ret
; Scrolling routines. vtscru scrolls up, vtscrd scrolls down 'scroll'
; rows. Top lines are saved in the circular buffer before scrolling up.
; When running under an Environment control number of line positions moved
; to be less than scrolling region.
; All registers are preserved.
;
; Screen-roll down. Move text down one line, for terminal emulator only.
;
vtscrd: push ax
push bx
push cx
push dx
mov ax,0700h ; scroll down whole region
mov ch,mar_top ; top margin line
xor cl,cl ; left most column
mov dh,mar_bot ; bottom margin line
mov dl,byte ptr low_rgt ; right most column
mov bh,scbattr ; attributes
mov bl,dh
sub bl,ch ; region size - 1 line
jz vscrd1 ; z = region is 1 line, do one scroll
mov al,scroll ; number of lines to scroll, from msz
vscrd1: cmp al,bl ; want to scroll more that than?
jbe vscrd2 ; be = no
push ax
mov al,bl ; limit to region-1 for Windows
int screen ; and do in parts
pop ax
sub al,bl ; get remainder
jmp short vscrd1 ; do next part
vscrd2: int screen ; scroll it down
pop dx
pop cx
pop bx
pop ax
ret
; Screen scroll up one line (text moves up) for terminal emulator use.
; When running under an Environment control number of line positions moved
; to be less than scrolling region.
vtscru: push ax
push bx
push cx
push dx
xor ch,ch
mov cl,scroll ; number of lines to scroll
or cl,cl
jnz vscru5
jmp vscru3 ; z = nothing to do
vscru5: cmp mar_top,0 ; scrolling the top screen line?
ja vscru2 ; a = no. don't save anything
push si
push di
push cx ; (BDT) save this around the call
call putcirc ; put screen lines in circular buffer
pop cx ; (BDT) restore the register
add linec,cx ; (BDT) increment the current line
mov cx,linec ; new current line number
sub cx,lcnt ; minus # in buf = qty new lines added
jc vscru4 ; c = not extending buffer
add lcnt,cx ; (BDT) increment the line counter
vscru4:
mov cx,lcnt ; (BDT) check: are we
cmp cx,lmax ; (BDT) beyond the end?
jbe vscru1b ; (BDT) be = no
sub cx,lmax ; (BDT) compute overflow count
add linef,cx ; (BDT) adjust the "first" line
mov cx,linef ; (BDT) check: time to wrap?
cmp cx,linee ; (BDT) ...
jb vscru1 ; (BDT) b = no
sub cx,linee ; (BDT) yup
mov linef,cx ; (BDT) adjust it
vscru1: mov cx,lmax ; (BDT) get the maximum line count
mov lcnt,cx ; (BDT) reset the line counter
mov linec,cx ; (BDT) reset the current line
vscru1b:
pop di
pop si ; now scroll the visible screen
vscru2: mov ax,0600h ; scroll up whole region
mov dh,mar_bot ; bottom row
mov dl,byte ptr low_rgt ; right most column
mov ch,mar_top ; top row of scrolling region
xor cl,cl ; left most column
mov bh,scbattr ; attributes
mov bl,dh
sub bl,ch ; region size - 1 line
jz vscru2b ; z = region is 1 line, do one scroll
mov al,scroll ; number of lines to scroll, from msz
vscru2a:cmp al,bl ; want to scroll more that than?
jbe vscru2b ; be = no
push ax
mov al,bl ; limit to region - 1 for Windows
int screen ; and do in parts
pop ax
sub al,bl
jmp short vscru2a ; do next part
vscru2b:int screen ; scroll up that region
vscru3: pop dx ; restore the rest of the regs
pop cx
pop bx
pop ax
ret
; (BDT) new screen-scrolling routines. Single, circular buffer
homwnd proc near ; "home" to start of the buffer
push cx ; save registers
mov cx,lxtra ; save this many lines
call putcirc ; save them
mov linec,0 ; reset the current pointer
call getcirc ; now get the new screen
pop cx ; restore registers
clc
ret
homwnd endp
endwnd proc near ; "end" to end of the buffer
push cx ; save registers
mov cx,lxtra ; save this many lines
call putcirc ; save them
mov cx,lcnt ; reset the current pointer
mov linec,cx ; save the results
call getcirc ; now get the new screen
pop cx ; restore registers
clc
ret
endwnd endp
dnwpg proc near ; scroll down 1 page
push cx ; save registers
mov cx,lxtra ; save this many lines
call putcirc ; save them
mov cx,linec ; reset the current pointer
add cx,lxtra ; to the next page
cmp cx,lcnt ; did we go past the end?
jbe dnwpg1 ; be = no, we're OK
mov cx,lcnt ; yup, back up
dnwpg1:
mov linec,cx ; save the results
call getcirc ; now get the new screen
pop cx ; restore registers
clc
ret
dnwpg endp
dnone proc near ; scroll down 1 line
push cx ; save registers
mov cx,lxtra ; save this many lines
call putcirc ; save them
mov cx,linec ; reset the current pointer
inc cx ; to the next line
cmp cx,lcnt ; oops, did we go past the end?
jbe dnone1 ; be = no, we're OK
mov cx,lcnt ; yup, back up
dnone1:
mov linec,cx ; save the results
call getcirc ; now get the new screen
pop cx ; restore registers
clc
ret
dnone endp
upwpg proc near ; scroll up 1 page
push cx ; save registers
mov cx,lxtra ; save this many lines
call putcirc ; save them
mov cx,linec ; reset the current pointer
sub cx,lxtra ; to the previous page
jge upwpg1 ; ge = not past end, we're OK
xor cx,cx ; yup, back up
upwpg1:
mov linec,cx ; save the results
call getcirc ; now get the new screen
pop cx ; restore registers
clc
ret
upwpg endp
upone proc near ; scroll up 1 line
push cx ; save registers
mov cx,lxtra ; save this many lines
call putcirc ; save them
mov cx,linec ; reset the current pointer
sub cx,1 ; to the previous line
jge upone1 ; ge = not past end, we're OK
xor cx,cx ; yup, back up
upone1:
mov linec,cx ; save the results
call getcirc ; now get the new screen
pop cx ; restore registers
clc
ret
upone endp
; Put cx lines into the circular buffer.
; Source is tv_segs:si which is the current screen address.
putcirc proc near ; put lines in the circular buffer
jcxz putcir9 ; z = no lines to save
cmp lmax,0 ; any buffer space?
je putcir9 ; e = no, nothing saved here
push es ; save ES for a tad
call scroff ; turn off the screen
mov si,tv_sego ; initial screen offset
mov ax,linef ; get the first line pointer
add ax,linec ; add the current line counter
dec ax ; get a running start
putcir1:inc ax ; increment the current line pointer
cmp ax,linee ; fallen off the end of the buffer?
jb putcir2 ; b = no, proceed
sub ax,linee ; back up to the buffer start
putcir2:push ax ; save the current line pointer
mul ppl ; compute the paragraph offset
add ax,iniseg ; add the initial segment
mov es,ax ; now we have the segment pointer
xor di,di ; initial buffer offset is 0
push cx ; save the number of lines
xor ch,ch ; get the number of characters to move
mov cl,crt_cols
push ds ; get the offset of the screen
mov ds,tv_segs ; get the segment of the screen
rep movsw ; move them
pop ds ; restore DS
pop cx ; restore the line count
pop ax ; restore the buffer counter
loop putcir1 ; go back for more
call scron ; turn the screen back on
pop es ; restore ES
putcir9:ret
putcirc endp
; Get CX lines from the circular buffer, non destructivly.
; Destination preset in es:di which is the current screen address.
getcirc proc near ; get lines from the circular buffer
mov cx,lxtra ; restore this many lines
jcxz getcir3 ; z = nothing to do
call scroff ; turn off the screen
push es ; save ES for a tad
mov es,tv_segs ; get the segment of the screen
mov di,tv_sego ; initial screen offset
mov ax,linef ; get the first line pointer
add ax,linec ; add the current line counter
dec ax ; get a running start
getcir1:inc ax ; increment the current line pointer
cmp ax,linee ; fallen off the end of the buffer?
jb getcir2 ; b = no, proceed
sub ax,linee ; back up to the buffer start
getcir2:push ax ; save the current line pointer
mul ppl ; compute the paragraph offset
add ax,iniseg ; add the initial segment
xor si,si ; initial offset is 0
push cx ; save the number of lines
xor ch,ch ; get the number of characters to move
mov cl,crt_cols ; ...
push ds ; save DS for a tad
mov ds,ax ; now we have the segment pointer
rep movsw ; move them
pop ds ; restore DS
pop cx ; restore the line count
push di ; save around update call
call scrsync ; synch Topview
pop di
pop ax ; restore the buffer counter
loop getcir1 ; go back for more
call scron ; turn the screen back on
pop es ; restore ES
getcir3:ret
getcirc endp
;
; CHKDSP - procedure to check for hardware support of 132 cols
; Supported hardware:
; ATI EGA and VGA Wonder
; AT&T
; Everex Viewpoint EV-659, FVGA-673, EV-678, Micro Enhancer Deluxe
; IBM XGA
; Paradise AutoSwitch EGA Mono, VGA Professional, VGA Plus, VGA Plus 16
; STB VGA/EM (Tseng TVGA)
; STB VGA/EM Plus (Tseng 4000), VGA/EM-16, VGA/EM-16 Plus
; Tseng Labs EVA board w/132-col kit installed
; Tseng Labs UltraPAK mono/Herc board w/132 column modes.
; Video 7 Vega Deluxe w/ 132X25.COM driver installed and VGA board.
; The routine checks for the presence of a 132-column-capable adapter. If
; one is found its handler executes the desired mode setting and returns
; carry clear; it returns carry set otherwise.
; Adding new boards - place an identification string in the data segment,
; construct a mode setting routine and insert it in the call list below
; (setting 132 column mode is byte AL non-zero). Byte AH is non-zero to
; avoid saving old screen and running scrini; it is used to set the screen
; width when starting/exiting Connect mode
;
chgdsp proc near
push es ; save all we use
push ax
push bx
push cx
push dx
push si
push di
mov temp,ax ; save set/reset flag from msz
cmp crt_cols,80 ; are we narrow?
jbe chgds3 ; be = narrow width now
or al,al ; resetting to narrow width?
jz chgds4 ; z = yes, do it
jmp chgdsx1 ; else we are there now
chgds3: or al,al ; resetting to narrow width?
jnz chgds4 ; nz = no, setting to wide
jmp chgdsx1 ; narrow width, we are there now
chgds4: or ah,ah ; are we connected now?
jnz chgds0 ; nz = no, skip flow control etc
mov ah,flowoff ; get xoff
or ah,ah ; flow control?
jz chgds4a ; z = none
call outchr ; send it
chgds4a:cmp byte ptr temp+1,0 ; exiting Connect mode?
jne chgds0 ; ne = yes
call savescr ; save current screen
mov ax,500 ; wait 500 millisec before video tests
call pcwait ; so don't mix screen and port intrpts
chgds0: call ckteva ; try Tseng Labs EVA
jnc chgds1 ; nc = found
call ckstbv ; try STB VEGA/EM
jnc chgds1 ; nc = found
call ckv7vd ; try Video 7 EGA Deluxe and VGA
jnc chgds1 ; nc = found
call ckatiw ; try ATI EGA Wonder
jnc chgds1 ; nc = found
call ckevrx ; try Everex Micro Enhancer Deluxe
jnc chgds1 ; nc = found
call ckevga ; try Everex EVGA-673
jnc chgds1 ; nc = found
call ckatt ; ATT boards
jnc chgds1 ; nc = found
call chkpa ; Paradise EGA/VGA boards
jnc chgds1 ; nc = found
call ckxga ; IBM XGA
jnc chgds1 ; nc = found
mov si,offset cols80 ; name of 80 column file
cmp byte ptr temp,0 ; setting 80 cols?
je chgdsx2 ; e = yes
mov si,offset cols132 ; use 132 column file
chgdsx2:mov di,offset dumpbuf ; a temp buffer for path= usage
call strcpy
mov ax,di ; spath wants ptr in ax
call spath
jc chgdsx ; c = file not found
mov si,ax ; crun wants ptr in si
call crun ; run the batch file, si = filespec
call serini ; reengage serial port, mode changes
mov ax,0c06h ; clear kbd buffer and do function
mov dl,0ffh ; console input
int dos ; discard character(s)
; Perform mode change
chgds1: cmp byte ptr temp+1,0 ; do without scrini stuff?
jne chgdsx1 ; ne = yes
cmp flags.modflg,1 ; is mode line enabled?
jbe chgds2 ; be = yes, and off or locally owned
mov flags.modflg,1 ; remove foreign ownership
chgds2: call scrini ; reset parameters
chgdsx: mov ah,flowon ; get flowon byte
or ah,ah ; using flow control?
jz chgdsx1 ; z = no
call outchr ; send it
chgdsx1:pop di ; restore what we saved
pop si
pop dx
pop cx
pop bx
pop ax
pop es
ret ; return to caller
; Individual tests for various 132-column boards
; Tseng LABS EVA and UltraPAK
ckteva: mov ax,0c000h ; seg addr for EVA
mov es,ax ; set into es register
mov di,76h ; offset of board's string
lea si,tsngid ; validation string
mov cx,tsnglen ; length of validiation string
cld
repe cmpsb ; compare strings
je ckteva2 ; e = strings match
mov ax,4d00h ; check for UltraPAK mono driver
int screen
cmp ax,5aa5h ; driver signature?
jne ckteva3 ; ne = no
mov ax,7 ; default to mono (7) for this board
cmp byte ptr temp,0 ; setting 132 columns?
je ckteva1 ; e = resetting to normal
mov ax,18h ; set to 132 cols (Set Mode 18H)
ckteva1:int screen
clc ; carry clear means success
ret
; an EVA board - check for 132 col kit
ckteva2:cmp byte ptr es:099h,0 ; check 132 col kit installed
jne catfnd ; ne = installed, do the mode change
ckteva3:stc ; indicate adapter not present
ret ; and exit
;
ckstbv: mov ax,0c000h ; STB's VGA/EM, VGA/EM-16, EM-16 Plus
mov es,ax ;
mov di,70h ; where to look for signature
lea si,stbvid ; the signature
mov cx,stbvlen ;
cld ;
repe cmpsb ; test
je catfnd ; e = found
mov di,70h ; where to look for signature
lea si,stavid ; the signature
mov cx,stavlen
cld
repe cmpsb ; test
je catfnd ; e = found
stc ; else say not there
ret ;
; ATI EGA Wonder
ckatiw: mov ax,0c000h ; seg addr for EGA Wonder
mov es,ax ; set into es register
mov di,012fh ; offset of message in ROM
lea si,atiwid ; offset of message here
mov cx,atilen ; length of validation string
cld
repe cmpsb ; compare strings
je catfnd ; e = they match
lea si,atiwid2 ; alternative signature
mov di,30h ; start at this offset
mov cx,atilen2 ; alternative signature length
mov ax,es:[di] ; get first two bytes
cmp al,atiwid2 ; string starts here?
je ckatiw1 ; e = yes
inc di ; try next location, just in case
cmp ah,atiwid2 ; or here?
je ckatiw1 ; e = yes
stc ; strings differ
ret
ckatiw1:repe cmpsb ; check the whole string
je catfnd ; e = matches the whole thing
stc ; fail on mismatch
ret
catfnd: mov ax,0003h ; prepare to reset video mode
cmp byte ptr temp,0 ; are we setting or resetting?
je catfnd1 ; e is reset, exit
mov ax,0023h ; set to 132 cols (Set Mode 23H)
catfnd1:int screen
clc ; carry clear means success
ret
chkpa: mov ax,0c000h ; load Paradise ROM BIOS address
mov es,ax
mov ax,0057h ; assume 132x25 mono display needed
mov di,0009h ; load EGA board identifier index
lea si,pmega1 ; Paradise Autoswitch Mono ident
mov cx,pmegal1
cld
repe cmpsb ; do identification strings match?
je chgpa2 ; e = yes, check num of display lines
mov di,007dh ; no, load VGA board identifier index
lea si,p30id ; Paradise VGA, other flavors
mov cx,p30ln
repe cmpsb ; do identification strings match?
je chgpa1 ; e = yes, check for color mode
stc ; fail
ret
chgpa1: cmp crt_norm,3 ; is the "normal" screen in color?
ja chgpa2 ; a = no, orig assumption is correct
mov ax,0055h ; assume 132x25 color required
chgpa2: cmp crt_lins,25 ; is the "normal" screen 25 lines?
jna chgpa3 ; na = yes, check num of cols needed
dec ax ; change assumption to 132x43
chgpa3: cmp byte ptr temp,0 ; switching to a 132 column mode?
jne chgpa4 ; ne = yes
mov al,crt_norm ; load "normal" display mode
chgpa4: int screen ; issue BIOS call to change display
clc ; success
ret
; Video 7 Vega Deluxe
ckv7vd: mov ax,0c000h ; seg addr for Vega rom bios
mov es,ax ; set into es register
mov di,002ah ; offset of message in ROM
lea si,vid7id ; offset of message here
mov cx,vid7len
cld
repe cmpsb ; compare strings
je cnv7fn1 ; e = same
mov di,002ah ; offset of ident string
mov si,offset vid7id2 ; Video 7 VGA board
mov cx,vid7len2
repe cmpsb
je cnv7fn2 ; e = found
cnv7fx: stc ; strings are different
ret
;
cnv7fn1:test byte ptr es:[03ffeh],1 ; is this a 'Deluxe' Vega?
jz cnv7fx ; z = nope, can't do it
mov ah,35h ; DOS Get Vector
mov al,10h ; Bios video interrupt
int dos ; get it into es:bx
mov di,bx ; es:bx is returned int 10h entry pnt
sub di,5ah ; back offset to msg in 132X25.COM
lea si,vid7id ; offset of validation message
mov cx,vid7len ; length of validation string
cld
repe cmpsb ; Look for repeat of msg by 132X25.COM
jne cnv7fn2 ; if different
mov al,crt_mode ; prepare to reset video mode
xor ah,ah
cmp byte ptr temp,0 ; are we setting or resetting?
je cnv7fn2a ; e is reset
mov ax,0000h ; set to 132 cols (old 40x25)
cnv7fn1a:int screen
clc
ret
cnv7fn2:mov ax,6f00h ; check for VegaBios driver
int screen
cmp bx,'V7' ; Video 7 Bios presence response
jne cnv7fx ; ne = not there
mov ax,6f01h ; al gets monitor type (mono,color,ega)
int screen
mov bx,51h ; presume mono 132x25, page 0
cmp crt_lins,42 ; 43 lines active?
jb cnv7fn2a ; b = no
inc bx ; use bx = 52h for 132x43
cnv7fn2a:
cmp al,10h ; analogue fixed freq (IBM 85xx)?
je cnv7fx ; e = yes, no 132 columns
cmp al,2 ; 1 = mono, 2 = color, above = ega
jb cnv7fn3 ; b = mono or unknown
mov bx,4fh ; presume med res color 132x25
je cnv7fn3 ; e = med res color, al = 2
mov bx,41h ; ega high res 132x25, enhanced mons
cmp crt_lins,42 ; 43 lines active?
jb cnv7fn3 ; b = no
inc bx ; use bx = 42h for 132x43
cnv7fn3:mov ax,6f05h ; set special mode found in bl
cmp byte ptr temp,0 ; resetting to 80 column mode?
jne cnv7fn4 ; ne = no, setting 132x25
mov al,crt_norm ; get normal mode
xor ah,ah ; set mode
cmp crt_lins,42 ; 43 lines active?
jb cnv7fn4 ; b = no
mov bl,40h ; use Video 7 mode 40h 80x43 for color
mov ax,6f05h ; and do special mode set
cnv7fn4:int screen ; special mode is in bl
mov ax,0f00h ; a nop screen bios command
int screen
clc
ret
ckevrx: mov ax,0c000h ; seg addr for Everex EV-659
mov es,ax ; set into es register
mov di,0047h ; offset of message in ROM
lea si,evrxid ; offset of message here
mov cx,evrxlen ; length of validation string
cld
repe cmpsb ; compare strings
jne ckfnr2 ; ne = strings differ
mov ah,crt_lins ; we recognize either 44 or 25 rows
cmp ah,43 ; equal to 44-1 rows?
jne ckfnr1 ; ne = no
mov ax,0070h ; Everex extended mode ident
mov bl,09h ; prepare to reset video mode to 80x44
cmp byte ptr temp,0 ; are we setting or resetting?
je ckfnr4 ; e is reset, exit
mov bl,0bh ; 132x44
int screen
clc
ret
ckfnr1: cmp ah,24 ; equal to 25-1 rows?
je ckfnr3 ; e = yes
ckfnr2: stc ; return failure
ret
ckfnr3: mov ax,0003h ; prepare to reset video mode
cmp byte ptr temp,0 ; are we setting or resetting?
je ckfnr4 ; e is reset, exit
mov ax,0070h ; Everex extended mode ident
mov bl,0ah ; 132x25
ckfnr4: int screen
clc
ret
ckevga: mov ax,0c000h ; Everex FVGA-673, EV-678 rom segment
mov es,ax
mov di,76h ; offset in rom for board's id string
lea si,evgid ; id string
mov cx,evglen ; length of id string
cld
repe cmpsb ; do they match?
je ckevg0 ; e = yes
mov di,9dh ; offset in ROM for board's ID string
lea si,evvid ; ID string
mov cx,evvlen ; length of ID string
cld
repe cmpsb ; do they match?
jne ckevg2 ; ne = no
ckevg0: mov ax,3 ; prepare to reset video mode
cmp byte ptr temp,0 ; setting or resetting mode?
je ckevg1 ; e = resetting, exit
mov ax,0070h ; mode for 132x25
mov bl,0ah ; Everex mode 0ah
ckevg1: int screen
clc
ret
ckevg2: stc ; say board not found
ret
; AT&T EGA/VGA boards
ckatt: mov ax,0c000h ; seg of first signature
mov es,ax
mov si,offset attvdc6 ; first pattern
mov di,35h ; test area
cld
mov cx,attvdlen ; length
repe cmpsb
je ckatt2 ; e = found
mov cx,attvdlen ; try second signature, same length
mov si,offset attvdc7
mov ax,0e000h ; seg of second signature
mov es,ax
mov di,10h ; test area
repe cmpsb
je ckatt2 ; e = found
stc ; not found
ret
ckatt2: mov al,crt_norm ; old mode
xor ah,ah
cmp byte ptr temp,0 ; resetting to 80 col?
je ckatt3 ; e = yes
mov ax,0055h ; 132 cols, set mode 55h
ckatt3: int screen
clc
ret
; IBM XGA 132 columns
ckxga: push bp ; (old BIOSes are still around)
push ds ; set es to data segment
pop es
mov ax,1b00h ; get functionality table
xor bx,bx
mov di,offset dumpbuf ; es:di is 64 bytes of workspace
int screen
cmp al,1bh ; is this call supported?
jne ckxgax ; ne = no, fail
les bx,dword ptr dumpbuf ; get the address of the modes info
test byte ptr es:[bx+2],10h ; is mode 14h supported?
jz ckxman ; z = no, try manual method for now
mov ax,3 ; assume resetting to mode 3, 80x25
cmp byte ptr temp,0 ; setting 132 columns?
je ckxga1 ; e = no, resetting to 80 columns
mov ax,14h ; invoke IBM XGA mode 14h, 132x25
ckxga1: int screen
ckxga2: pop bp
clc ; say success
ret
ckxgax: pop bp
mov xga_reg_base,-2 ; flag saying no XGA Adapter found
stc ; say failure
ret
ckxman: call dword ptr fxgaman ; do tests/sets manually
pop bp
jnc ckxman1 ; nc = success
mov xga_reg_base,-2 ; flag saying no XGA Adapter found
ckxman1:ret
chgdsp endp
code ends
; XGA mode setting via going to the hardware manually
; Code furnished by Bert Tyler, National Institue of Health
code1 segment
assume cs:code1
xgaman proc FAR
cmp xga_reg_base,-2 ; has the XGA detector already failed?
je xgafail ; e = yes, fail again
cmp xga_reg_base,-1 ; have we already found the XGA?
je xga_loc ; e = no
jmp xga_do1 ; yes, process it
xga_loc:push es
mov ah,35h ; DOS get interrupt vector
mov al,15h ; Int 15h
int dos ; returns vector in es:bx
mov ax,es ; segment part
pop es
or ax,ax ; undefined vector?
jz xgafail ; z = yes
mov dx,-1 ; start with an invalid POS address
mov ax,0c400h ; look for POS base address
int 15h ; (Microchannel machines only)
jc xgafail ; c = error, not a MC machine
mov word ptr dumpbuf,dx ; save pos_base_address
xor cx,cx ; check all MCA slots & motherboard
cmp dx,-1 ; do we have a good POS?
jne xga_lp1 ; ne = yes, proceed with MCA checks
xgafail:stc ; fail
ret
xga_lp1:cli ; no interrupts, please
cmp cx,0 ; treat the motherboard differently?
jne xga_sk4 ; ne = yes
mov al,0dfh ; enable the motherboard for setup
mov dx,94h
out dx,al
jmp short xga_sk5
xga_sk4:mov ax,0c401h ; enable an MCA slot for setup
mov bx,cx ; this slot
int 15h
xga_sk5:mov dx,word ptr dumpbuf ; get pos record for the slot
in ax,dx ; ID
mov word ptr dumpbuf+2,ax
add dx,2 ; compute IO Res Base
in al,dx ; get POS data byte1
and ax,0eh ; muck about with it to get reg base
shl ax,1
shl ax,1
shl ax,1
add ax,2100h
mov xga_reg_base,ax
cmp cx,0 ; treat the motherboard differently?
jne xga_sk6 ; ne = yes
mov al,0ffh ; enable the motherboard for normal
out 094h,al
jmp short xga_sk7
xga_sk6:mov ax,0c402h ; enable the MCA slot for normal
mov bx,cx ; this slot
int 15h
xga_sk7:sti ; interrupts on again
mov ax,word ptr dumpbuf+2 ; is an XGA adapter on this slot?
cmp ax,08fd8h
jae xga_sk8 ; ae = yes
jmp xga_lp2 ; try another slot
xga_sk8:cmp ax,08fdbh ; still within range?
jbe xga_sk9 ; be = yes
jmp xga_lp2 ; no, try another slot
xga_sk9:mov dx,xga_reg_base ; is there a monitor on this slot?
add dx,0ah
mov al,052h
out dx,al
mov dx,xga_reg_base
add dx,0bh
in al,dx
and al,0fh
cmp al,0fh
jne xga_ska ; ne = yes
jmp xga_lp2 ; no
xga_ska:mov dx,xga_reg_base ; is this XGA in VGA mode?
in al,dx
test al,1
jnz xga_do1 ; nz = yes, found it!
xga_lp2:inc cx ; try another adapter?
cmp cx,9 ; done all slots?
ja xga_no ; a = yes
jmp xga_lp1 ; no, try another slot
xga_no: jmp xgafail ; fail
; *finally* put the XGA into 132-column or 80-column mode
xga_do1:cmp byte ptr temp,0 ; setting 80-column mode?
jne xga_do2 ; ne = no, 132 columns
jmp xga_do3 ; do 80 column mode
; 132-column mode routine
xga_do2:mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,0ah
mov ax,1550h
out dx,ax
mov ax,1450h
out dx,ax
mov ax,0454h
out dx,ax
mov ax,1202h ; select 400 scan lines
mov bl,30h
int screen
mov ax,0+3 ; set video mode 3
int screen
mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,0ah
mov al,50h
out dx,al
inc dx
in al,dx
or al,1
out dx,al
mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,0ah
mov al,50h
out dx,al
inc dx
in al,dx
and al,0fdh
out dx,al
mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,0ah
mov al,50h
out dx,al
inc dx
in al,dx
and al,0fch
out dx,al
mov dx,xga_reg_base ; (the manual doesn't explain...)
mov al,3
out dx,al
mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,0ah
mov ax,0154h
out dx,ax
mov ax,8070h
out dx,ax
mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,0ah
mov al,50h
out dx,al
inc dx
in al,dx
and al,0efh
out dx,al
mov dx,03d4h ; (the manual doesn't explain...)
mov ax,11h
out dx,al
inc dx
in al,dx
and al,7fh
out dx,al
mov dx,03d4h ; (the manual doesn't explain...)
mov ax,0
out dx,al
inc dx
mov ax,0a4h
out dx,al
mov dx,03d4h ; (the manual doesn't explain...)
mov ax,1
out dx,al
inc dx
mov ax,83h
out dx,al
mov dx,03d4h ; (the manual doesn't explain...)
mov ax,2
out dx,al
inc dx
mov ax,84h
out dx,al
mov dx,03d4h ; (the manual doesn't explain...)
mov ax,3
out dx,al
inc dx
mov ax,83h
out dx,al
mov dx,03d4h ; (the manual doesn't explain...)
mov ax,4
out dx,al
inc dx
mov ax,90h
out dx,al
mov dx,03d4h ; (the manual doesn't explain...)
mov ax,5
out dx,al
inc dx
mov ax,80h
out dx,al
mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,0ah
mov ax,0a31ah
out dx,ax
mov ax,001bh
out dx,ax
mov dx,03d4h ; (the manual doesn't explain...)
mov ax,13h
out dx,al
inc dx
mov ax,42h
out dx,al
mov dx,03d4h ; (the manual doesn't explain...)
mov al,11h
out dx,al
inc dx
in al,dx
or al,80h
out dx,al
mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,0ah
mov al,50h
out dx,al
inc dx
in al,dx
or al,3
out dx,al
mov dx,03c4h ; (the manual doesn't explain...)
mov ax,1
out dx,al
inc dx
in al,dx
or al,1
out dx,al
mov dx,03dah ; (the manual doesn't explain...)
in al,dx
mov dx,003c0h ; (the manual doesn't explain...)
mov al,13h
out dx,al
xor al,al
out dx,al
mov al,20h
out dx,al
mov ax,40h ; tell the BIOS we have 132 columns
mov es,ax
mov byte ptr es:[4ah],132 ; set Bios screen width data area
clc ; return success
ret
; Set 80 column mode
xga_do3:mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,01h
xor al,al
out dx,al
mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,4
xor al,al
out dx,al
mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,5
mov al,0ffh
out dx,al
mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,0ah
mov ax,0ff64h
out dx,ax
mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,0ah
mov ax,1550h
out dx,ax
mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,0ah
mov ax,1450h
out dx,ax
mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,0ah
mov ax,0051h
out dx,ax
mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,0ah
mov ax,0454h
out dx,ax
mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,0ah
mov ax,7f70h
out dx,ax
mov dx,xga_reg_base ; (the manual doesn't explain...)
add dx,0ah
mov ax,202ah
out dx,ax
mov dx,xga_reg_base ; (the manual doesn't explain...)
;; add dx,00h
mov al,1
out dx,al
mov dx,03c3h ; (the manual doesn't explain...)
mov al,1
out dx,al
mov ax,1202h ; select 400 scan lines
mov bl,30h
int screen
mov ax,0+3 ; set video mode 3
int screen
clc ; return success
ret
xgaman endp
code1 ends
code segment
assume cs:code
; Character write/read and cursor manipulation routines for terminal emulator
; All registers other than returned values are preserved.
; Read char and attributes under cursor.
; Returns AL = character, AH = video attributes
getatch proc near
push bx
mov ah,8 ; read char and attributes
xor bh,bh ; page 0
int screen ; Bios video call
pop bx
ret
getatch endp
; Read cursor position
; DH = column, DL = row, both counted from 0,0 at upper left corner
getpos proc near
push ax
push bx
mov ah,3 ; get cursor position
xor bh,bh ; page 0
int screen
pop bx
pop ax
ret
getpos endp
; Set cursor postion
; DH = column, DL = row, both counted from 0,0 at upper left corner
setpos proc near
push ax
push bx
mov ah,2 ; set cursor
xor bh,bh ; page 0
int screen
pop bx
pop ax
ret
setpos endp
; Write char and attribute to screen at cursor position, do not move cursor.
; AL = char, AH = video attribute
setatch proc near
push ax
push bx
push cx
mov cx,1 ; one char
mov bl,ah ; attribute
xor bh,bh ; page 0
mov ah,9 ; write char, do not move cursor
int screen
pop cx
pop bx
pop ax
ret
setatch endp
; Write char to screen at cursor position, move cursor, use current attributes
; AL = char.
putchar proc near
push ax
push bx
mov ah,0eh ; write char, increment cursor
xor bh,bh ; page 0
int screen
pop bx
pop ax
ret
putchar endp
; Get bold video attribute bit
; Enter with AH = video attribute byte, returns AH = bold attribute bit
getbold proc near
and ah,att_intensity ; select bold bit
xor ah,userbold ; invert with user bold
ret
getbold endp
; Set bold video attribute bit
; Enter with AH = video attribute byte
setbold proc near
or ah,att_intensity ; set bold bit
xor ah,userbold ; invert with user bold
ret
setbold endp
; Clear bold video attribute bit
; Enter with AH = video attribute byte, returns new attribute byte in AH
clrbold proc near
and ah,not att_intensity ; clear bold bit
or ah,userbold ; invert with user bold
ret
clrbold endp
; Get blink video attribute bit
; Enter with AH = video attribute byte, returns AH = blink attribute bit
getblink proc near
and ah,att_blink ; get blink bit
ret
getblink endp
; Set blink video attribute bit
; Enter with AH = video attribute byte
setblink proc near
or ah,att_blink ; set blink bit
ret
setblink endp
; Clear blink video attribute bit
; Enter with AH = video attribute byte, returns new attribute byte in AH
clrblink proc near
and ah,not att_blink ; clear blink bit
ret
clrblink endp
; Get underline video attribute bit
; Enter with AH = video attribute byte, returns AH = underline attribute bit
getunder proc near
ret
getunder endp
; Set underline video attribute bit
; Enter with AH = video attribute byte, video_state (0=normal)
; Return AH holding new attribute byte, new video_state.
setunder proc near
cmp crt_mode,7 ; monochrome display adapter mode?
je setund2 ; e = yes, otherwise reverse video
jmp setrev
setund2:call brkatt ; break apart attributes
or al,att_underline ; set underline bit
call addatt ; reassemble attributes
ret
setunder endp
; Clear underline video attribute bit
; Enter with AH = video attribute byte, returns new attribute byte in AH and
; new video_state.
clrunder proc near
cmp crt_mode,7 ; monochrome display adapter mode?
je clrund2 ; e = yes, otherwise reverse video
jmp clrrev
clrund2:call brkatt ; break apart attributes
and al,not att_underline ; turn off underline bit
call addatt ; reassemble attributes
ret
clrunder endp
setrev proc near
cmp video_state,0 ; normal video
jne setrev1 ; ne = no, reversed already
call revideo ; do reversal
mov video_state,1 ; say reversed
setrev1:ret
setrev endp
clrrev proc near
cmp video_state,0 ; normal video?
je clrrev1 ; e = yes
call revideo ; do reversal
mov video_state,0 ; say normal
clrrev1:ret
clrrev endp
; Compute reversed video attribute byte. Normally preserves blink/bold.
; Enter with AH = video attribute byte, returns new attribute byte in AH
revideo proc near
call brkatt ; separate colors from blink/bold
rol ah,1 ; reverse foreground & background
rol ah,1 ; RGB bits
rol ah,1
rol ah,1
call addatt ; reinsert bold/blink bits
ret
revideo endp
; This routine picks an attribute apart into its component "parts" - the
; base attribute for the screen and the "extras" - i.e., blink, intensity
; and underline.
; enter with ah = a cursor attribute
; return ah = base attribute for screen (07H normal, 70H reverse).
; al = "extra" attributes
; Note that there is a complementary routine, addatt, for putting attributes
; back together.
brkatt: xor al,al ; Clear returned "extra" attributes
test ah,att_intensity ; intensity attribute on?
jz brkat3 ; z = no, check blink
or al,att_intensity ; set intensity
brkat3: test ah,att_blink ; blink on?
jz brkat4 ; z = no
or al,att_blink ; set blink
brkat4: and ah,not(att_intensity+att_blink) ;strip blink/bold, leave color
cmp crt_mode,7 ; monochrome display adapter mode?
jne brkat2 ; ne = no, cut this short for color
test ah,att_low_mask ; are any of these on?
jnz brkat1 ; nz = yes, can't be underline
test ah,att_underline ; underline?
jz brkat2 ; z = no, some kind of reverse video
or al,att_underline ; say underline
test ah,70h ;;att_reverse ; reverse video + underline?
jz brkat1 ; z = no, fix up low nibble
and ah,not att_underline ; clear the underline bit in ah
ret
brkat1: or ah,att_normal ; normal, turn on all normal bits
brkat2: ret
; This routine builds a cursor attribute given the base attribute for the
; screen background and the "extra" attributes we want (blink, etc.).
; enter with ah = base attribute for background (07H or 70H)
; al = "extra" attributes (89H for all three)
; return ah = base combined with "extras".
addatt: test al,att_underline ; want underline?
jz addat1 ; z = no, no need for hack
and ah,not att_low_mask ; clear background colors
addat1: or ah,al ; Or in the attributes
ret
; This routine is called when we want to reverse everything on the screen
; from normal to reverse video, or vice versa. It is called only when
; the decscnm attribute is changed.
; Call: no arguments.
revscn proc near
push ax
push bx
push cx
push dx
mov dh,byte ptr low_rgt+1 ; Compute last screen offset in ax
inc dh ; One more row to catch mode line
mov dl,crt_cols ; physical width
dec dl ; and we count from 0
call scrloc ; get screen offset into ax
mov cx,ax ; Save it in cx for a minute
add cx,2
sar cx,1 ; In 16-bit words please
push di ; Save some more acs
push es
push cx ; save word count for Topview
mov ax,tv_segs ; Get address of screen in ax, es:di
mov es,ax
xor di,di
call scroff ; Turn screen off if color card
cld
revsc1: mov ax,es:[di] ; Fetch a word
mov bl,al ; Save the character
call revideo ; get reversed video attributes (AH)
call addatt ; Put attributes back together
mov al,bl ; Restore character
stosw ; Stuff into screen memory
loop revsc1 ; Loop for entire screen
pop cx ; recover word count for Topview
call scrsync ; synch with Topview
call scron ; Turn screen back on if color card
pop es ; Restore segment register
pop di ; And destination index
pop dx
pop cx
pop bx
pop ax
ret
revscn endp
; IBM PC worker for insert/delete cx characters at and including cursor.
; dh= logical cursor row, dl= logical cursor column,
; cx has character repeat count, bl = logical screen width-1,
; bh = +1 for insert, -1 for delete chars.
; Double width lines have cx and dl doubled by our caller. Writing right to
; left is managed here.
insdecom proc near
push es
push ax
push cx
push dx
push si
push di
mov temp,0 ; worker temp
mov skip,cx ; number of chars to insert/delete
call scrseg ; pick up screen segment in es:di,ax
test vtemu.vtflgop,vswdir ; writing left to right?
jz insdec1 ; z = yes, no changes needed
sub dl,bl ; logical to physical cursor position
neg dl ; make dl positive again
xor bl,bl ; right-to-left, edge is left margin
; bl is now logical eol
insdec1:mov cl,dl ; physical cursor dl saved here
or bh,bh ; insert?
jl insdec2 ; l = no, leave dl at cursor column
mov dl,bl ; insert uses logical end of line
insdec2:call scrloc ; ax = offset in regen buffer
add di,ax ; es:di = destination so far
mov si,di ; align source to be same place
or bh,bh ; inserting?
jge insdec4 ; ge = yes
test vtemu.vtflgop,vswdir ; writing right to left?
jnz insdec4a ; nz = yes
insdec3:add si,skip ; delete
add si,skip
mov byte ptr temp+1,0 ; remember direction here as 0=cld
cld
jmp short insdec5
insdec4:test vtemu.vtflgop,vswdir ; insert, writing right to left?
jnz insdec3 ; nz = yes
insdec4a:sub si,skip
sub si,skip
mov byte ptr temp+1,0 ; remember direction here as 1=std
std
insdec5:call scroff ; video off
xor ch,ch
sub cl,bl ; cursor - margin
jnc insdec6 ; nc = non-negative
neg cl ; make positive
insdec6:inc cx ; include cursor location too
sub cx,skip ; cx = number chars to be moved
jle insdec7 ; le = none, just write spaces
mov byte ptr temp,cl ; number of chars modified
push ds
push es
pop ds
rep movsw ; mov cx chars from es:[si] to es:[di]
pop ds
insdec7:mov cx,skip ; number chars skipped
jcxz insdec8 ; z = none
add byte ptr temp,cl ; number chars modified
mov al,' ' ; get fill pattern
mov ah,scbattr ; attribute
rep stosw ; fill at the end
insdec8:cld ; restore direction flag
call scron ; video back on for CGA screens
mov cl,byte ptr temp ; number of char cells touched
xor ch,ch
cmp byte ptr temp+1,0 ; was Direction bit set?
je insdec9 ; e = no
add di,cx ; make di be its highest value
insdec9:call scrsync ; synch Topview
pop di
pop si
pop dx
pop cx
pop ax
pop es
ret
insdecom endp
; Set coloring attributes.
; Enter with AH holding current video attribute byte,
; BL holding ANSI color code (30-37 or 40-47) where 30's are foreground,
; 40's are background. ANSI colors are 1 = red, 2 = green, 4 = blue.
; Return new attribute byte in AH.
setcolor proc near
cmp video_state,0 ; normal video currently?
je setcol0 ; e = yes
mov al,ah ; make a copy
and ax,7788h ; strip bold,blink, keep both in al
rol ah,1 ; get colors in right parts
rol ah,1 ; of ah = back, al = foreground
rol ah,1
rol ah,1
call setcol0 ; set fore or background color
rol ah,1 ; reverse coloring again
rol ah,1
rol ah,1
rol ah,1
or ah,al ; put back blink and bold
ret
setcol0:cmp bl,30 ; ANSI color series?
jb setcol7 ; b = no
cmp bl,37 ; foreground set (30-37)?
ja setcol4 ; a = no, try background set
sub bl,30 ; take away the bias
and ah,not 07H ; clear foreground bits
test bl,1 ; ANSI red?
jz setcol1 ; z = no
or ah,4 ; IBM red foreground bit
setcol1:test bl,2 ; ANSI & IBM green?
jz setcol2 ; z = no
or ah,2 ; IBM green foreground bit
setcol2:test bl,4 ; ANSI blue?
jz setcol3 ; z = no
or ah,1 ; IBM blue foreground bit
setcol3:ret
setcol4:cmp bl,40 ; background color set?
jb setcol7 ; b = no
cmp bl,47 ; background set is 40-47
ja setcol7 ; nb = no, not a color command
sub bl,40 ; take away the bias
and ah,not 70H ; clear background bits
test bl,1 ; ANSI red?
jz setcol5 ; z = no
or ah,40h ; IBM red background bit
setcol5:test bl,2 ; ANSI & IBM green?
jz setcol6 ; z = no
or ah,20h ; IBM green background bit
setcol6:test bl,4 ; ANSI blue?
jz setcol7 ; z = no
or ah,10h ; IBM blue background bit
setcol7:ret
setcolor endp
; Routine to do keyclick if flag is set, no arguments
vclick proc near
test vtemu.vtflgop,vskeyclick ; is keyclick flag on?
jz vclick1 ; z = no, just return
push bx
push di
mov di,500 ; 500 Hertz
mov bx,1 ; For 1 millisecond
call vtsound ; Do it
pop di ; Restore the ACs
pop bx
vclick1:ret
vclick endp
; Routine to do VT100-style bell, no arguments
vtbell proc near
cmp belltype,1 ; visual bell?
je vtbell1 ; e = yes
ja vtbell2 ; a = no bell
push di ; audible bell
push bx
mov di,880 ; 880 Hertz
mov bx,40 ; For 40 ms
call vtsound ; Do it
pop bx
pop di
ret
vtbell1:call revscn ; reverse screen
push ax
mov ax,40 ; for 40 milliseconds
call pcwait
pop ax
call revscn ; put back
vtbell2:ret
vtbell endp
; Routine to make noise of arbitrary frequency for arbitrary duration.
; Similar to routine (with typo removed) in "IBM PC Assembly Language:
; A Guide for Programmers", Leo J. Scanlon, 1983 Robert J. Brady Co.,
; Bowie, MD., page 270. Modified by J R Doupnik to use 0.1 millsec interval.
; Call: di/ frequency in Hertz.
; bx/ duration in 1 millisecond units
vtsound proc near
push ax ; save regs
push cx
push dx
mov al,0B6H ; write timer mode register
out 43H,al
mov dx,14H ; timer divisor is
mov ax,4F38H ; 1331000/frequency
div di
out 42H,al ; write timer 2 count low byte
mov al,ah
out 42H,al ; write timer 2 count high byte
in al,61H ; get current port B setting
or al,3 ; turn speaker on
out 61H,al
mov ax,bx ; number of milliseconds to wait
call pcwait ; do the calibrated wait
in al,61H ; get current port B setting
and al,0fch ; turn off speaker and timer
out 61H,al
pop dx ; restore regs
pop cx
pop ax
ret
vtsound endp
code ends
end